/* =====================================================================
   px_ui / tech_update_shell_html — the shell's stylesheet.

   An asset because the server strips the text out of a template's
   <style> element, so these rules would never reach the
   page. It is head-linked from anvil.yaml native_deps.head_html, which
   is also the only thing that styles the designer canvas.

   NOT :where()-SCOPED, and that is deliberate. Every selector below
   already begins .px-tech-update, so wrapping them would DROP a class
   of specificity from every descendant rule
   (.px-tech-update__article h2 at (0,2,0) becoming
   :where(.px-tech-update) .px-tech-update__article h2 at (0,1,0)).

   CSS ORDER AUDIT — no rule here needs a second class. A head link is
   earlier than every runtime-injected sheet, so a rule that could win a
   specificity tie only by document order would lose it. There is no
   such rule. The .px-tech-update names are spelled in no host repo, in
   no host theme asset, and in none of this dependency's
   runtime-injected sheets: px_theme/_px_theme_css.py declares only the
   shared .px-btn, .px-card, .px-input, .px-modal, .px-toast and
   themed-scrollbar families, px_brand_css.py is .pxbrand-only, and the
   MAR sheets are .pxm-only and are never injected on a page that mounts
   this form. The one plausible tie was
   .px-tech-update ... box-sizing: border-box against an injected
   .px-something setting box-sizing at the same specificity; there is no
   such rule. Re-run that audit if a later revision adds a shared .px-
   rule that reaches inside this article.

   MOUNT HAZARD, and it is not a specificity question. The root rule
   below carries `min-height: 100%` and `overflow-x: hidden`, and it is the
   form root. `overflow-x: hidden` with `overflow-y: visible`
   computes `overflow-y: auto`, so the root is a scroll container, and
   `min-height: 100%` resolves against whatever box the host mounts it
   in. Mounted as a flex item of PxNavDrawerLayout's `.px-nav-content`,
   the non-visible overflow removes the item's automatic minimum size:
   the article scrolls in a nested box instead of the port, and the
   layout's `.px-nav-layout.px-modal-open .px-nav-content` scroll lock
   stops holding the page behind an open dialog. The fix, for the first
   host that hits it, is `overflow-x: clip` on
   `.px-tech-update__container`, never a change to the root. Same
   contract in the class docstring of
   client_code/px_ui/tech_update_shell_html/__init__.py.

   A --px- token that does not resolve leaves the whole declaration
   invalid, and the colour policy below bans fallbacks, so this sheet
   paints geometry and no colour on a canvas with no token source. That
   is expected on this app's designer canvas, which runs no Python and
   so never reaches ensure_theme_injected().
   ===================================================================== */

/* =====================================================================
   px_ui / tech_update_shell_html — shared management tech-update
   article shell (6C-51 / 6T-09).

   WHAT LIVES HERE. Only the chrome that every management tech-update
   Form already shares, byte-for-byte, at HEAD: the eyebrow sticker, the
   display title with its accent underline, the published-on line, the
   footer wordmark badge, the page container geometry, the base
   typography and the responsive + print rules. The ARTICLE stays with
   the host — it arrives through the default slot below and this file
   states nothing about its content.

   CSS SCOPING (planner-locked). Every rule is prefixed .px-tech-update.
   The shared theme sheet (px_brand_css.py :: PX_BRAND_CSS) is
   deliberately NOT edited for this component: a Form-scoped block
   cannot collide with the other screens that consume the same tokens.

   COLOUR POLICY (3C-07 / 3T-07 / OD-02 / 3C-03b, hard):
     * ZERO colour literals. Management's private palette
       (--bg-cream / --bg-white / --text-dark / --text-mid / --border /
       --yellow / --font-main) maps onto the unified set as:
         --bg-cream  -> --px-bg-deep        --border    -> --px-border-strong
         --bg-white  -> --px-bg-card        --yellow    -> --px-accent
         --text-dark -> --px-text-primary   (on accent) -> --px-accent-on
         --text-mid  -> --px-text-secondary --font-main -> --px-font-display / --px-font
     * NO var() fallbacks. An unresolved token must fail visibly rather
       than silently paint a stand-in.
     * The decorative SVG in the footer paints with currentColor, so it
       inherits the badge's token colour instead of carrying its own.
   ===================================================================== */

.px-tech-update {
  font-family: var(--px-font);
  background: var(--px-bg-deep);
  color: var(--px-text-primary);
  line-height: 1.6;
  font-weight: 500;
  min-height: 100%;
  overflow-x: hidden;
}

.px-tech-update * { box-sizing: border-box; }

/* ------------------------------------------------------ container --- */
.px-tech-update__container {
  max-width: 1200px;
  width: 100%;
  margin: 0 auto;
  padding: 40px 24px 100px;
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------- header --- */
.px-tech-update__header {
  margin-bottom: 40px;
  position: relative;
}

.px-tech-update__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--px-accent);
  color: var(--px-accent-on);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 10px 20px;
  border: 3px solid var(--px-border-strong);
  border-radius: var(--px-radius-sm);
  box-shadow: 4px 4px 0 var(--px-border-strong);
  margin-bottom: 24px;
}

.px-tech-update__eyebrow::before { content: "\1F4C5"; }

/* An absent eyebrow renders NOTHING — the shell never substitutes a
   stand-in label for one the host did not state. */
.px-tech-update__eyebrow[hidden] { display: none; }

.px-tech-update__title {
  font-family: var(--px-font-display);
  font-size: clamp(2.8rem, 7vw, 4.5rem);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.03em;
  margin: 0 0 16px;
  position: relative;
}

/*
  The donors underline ONE authored word of the title
  (``h1 .highlight::after``). That needs markup INSIDE the title, and
  the title crosses this boundary as text, never as markup — so the
  accent becomes a rule under the whole heading instead of a per-word
  highlight.
*/
.px-tech-update__title-rule {
  width: 120px;
  height: 16px;
  margin: 0 0 16px;
  background: var(--px-accent);
  transform: rotate(-1deg);
}

.px-tech-update__published {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--px-text-secondary);
}

/* ------------------------------------ article slot (host content) --- */
/*
  The typography below is the BASE the shell declares for whatever the
  host drops into the slot. The donor Forms share their body font,
  colour, line-height and weight and their h1 scale; they share no h2/h3
  rule, so the two step-downs here are the shell's own declared scale
  rather than an extracted one.
  Everything below h3 simply inherits.
*/
.px-tech-update__article {
  display: block;
  width: 100%;
}

.px-tech-update__article h2 {
  font-family: var(--px-font-display);
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 40px 0 16px;
}

.px-tech-update__article h3 {
  font-family: var(--px-font-display);
  font-size: clamp(1.2rem, 2.6vw, 1.5rem);
  font-weight: 700;
  line-height: 1.25;
  margin: 32px 0 12px;
}

.px-tech-update__article p { margin: 0 0 16px; }

.px-tech-update__article ul,
.px-tech-update__article ol { margin: 0 0 16px 24px; }

.px-tech-update__article li { margin-bottom: 8px; }

.px-tech-update__article a {
  color: var(--px-accent);
  text-decoration: underline;
}

.px-tech-update__article small,
.px-tech-update__article .px-tech-update__muted { color: var(--px-text-secondary); }

/* --------------------------------------------------------- footer --- */
.px-tech-update__footer {
  text-align: center;
  padding: 40px 0 20px;
}

.px-tech-update__footer-badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--px-bg-card);
  color: var(--px-text-primary);
  padding: 12px 24px;
  border: 3px solid var(--px-border-strong);
  border-radius: var(--px-radius-pill);
  box-shadow: 4px 4px 0 var(--px-border-strong);
}

.px-tech-update__footer-badge span {
  font-weight: 700;
  font-size: 0.9rem;
}

/* ----------------------------------------------------- responsive --- */
@media (max-width: 768px) {
  .px-tech-update__container { padding: 24px 16px 60px; }
  .px-tech-update__title { font-size: 2.2rem; }
  .px-tech-update__eyebrow { margin-bottom: 16px; }
}

/* ---------------------------------------------------- print chrome --- */
/*
  Shared chrome: no management tech-update Form carries a @media print
  rule. The row asks for print chrome, so it is
  declared here once, for every host, rather than twelve times.

  Print drops the screen-only decoration — the offset shadows, the
  rotated accent underline and the heavy outlines all cost toner and
  none of them carry meaning on paper — and keeps the landmarks.
*/
@media print {
  .px-tech-update {
    background: none;
    min-height: 0;
  }

  .px-tech-update__container {
    max-width: none;
    padding: 0;
  }

  .px-tech-update__eyebrow,
  .px-tech-update__footer-badge {
    box-shadow: none;
    border-width: 1px;
  }

  .px-tech-update__eyebrow {
    background: none;
    color: var(--px-text-primary);
  }

  .px-tech-update__footer-badge { background: none; }

  .px-tech-update__title-rule { display: none; }

  .px-tech-update__title { font-size: 2rem; }

  .px-tech-update__article h2,
  .px-tech-update__article h3 { break-after: avoid; page-break-after: avoid; }

  .px-tech-update__article li,
  .px-tech-update__article p { break-inside: avoid; page-break-inside: avoid; }

  .px-tech-update__footer { break-before: avoid; page-break-before: avoid; }
}
