/* Responsive layer for the prerendered pages.
 *
 * The design sources style almost everything through inline style attributes,
 * which no stylesheet rule can beat on specificity alone — hence the
 * !important overrides below.
 *
 * Two tiers, because the header and the content stop fitting at different
 * widths:
 *
 *   <= 1239px  The desktop header (logo + 6-7 nav cells + chip + CTA) needs
 *              ~1240px. Below that it is swapped for the disclosure panel, and
 *              fixed pixel widths are allowed to shrink. Multi-column layouts
 *              are kept — a tablet has room for them.
 *   <=  900px  Phone territory: grids collapse to one column, the folio rail
 *              and framed-viewport inset are dropped, micro-type is raised to a
 *              readable size.
 *
 * Design grammar is preserved throughout: square geometry (radius 0), hairline
 * rules, IBM Plex Mono micro-labels, no rounded cards.
 */

:root {
  --tdf-rule-sm: rgba(10, 10, 10, 0.18);
}

/* The nav button and panel are in the markup at every width; only the
   breakpoint reveals them. */
.tdf-navbtn,
.tdf-navpanel {
  display: none;
}

/* A page whose header keeps its own disclosure at every width (v7's INDEX).
   These rules are only the dropdown's geometry — full-bleed sheet under the
   bar, capped to the viewport. What the open panel looks like is defined once,
   in the index block below, for every width. */
.tdf-navpanel[data-always='true'][data-open='true'] {
  display: block !important;
  position: absolute;
  left: 0;
  right: 0;
  z-index: 69;
  border-top: 1px solid var(--tdf-rule-sm);
  background: #fff;
  max-height: calc(100dvh - var(--tdf-hdr, 60px));
  overflow-y: auto;
}

/* The menu control's bars, and their morph to an X. Outside the phone tier
   because the landing INDEX now carries them at every width. */
.tdf-navbtn-bars {
  position: relative;
  display: block;
  width: 16px;
  height: 9px;
  flex: none;
}

.tdf-navbtn-bars::before,
.tdf-navbtn-bars::after {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.18s cubic-bezier(0.23, 1, 0.32, 1);
}

.tdf-navbtn-bars::before { top: 0; }
.tdf-navbtn-bars::after { bottom: 0; }

.tdf-navbtn[aria-expanded='true'] .tdf-navbtn-bars::before {
  transform: translateY(3.75px) rotate(45deg);
}

.tdf-navbtn[aria-expanded='true'] .tdf-navbtn-bars::after {
  transform: translateY(-3.75px) rotate(-45deg);
}

/* ============================================================
   The index — what an open menu is, at every width
   ============================================================

   One treatment whether INDEX opens it over a desktop or the menu button
   opens it on a phone: the destinations at display size, numbered, with the
   address at the foot. Selectors repeat [data-open='true'] to outrank the
   data-always geometry above without an specificity arms race elsewhere —
   this block sits later in the file, so an equal tie also breaks its way. */

.tdf-navpanel[data-open='true'][data-open='true'] {
  display: flex !important;
  flex-direction: column;
  counter-reset: tdfnav;
  border-top: 1px solid var(--tdf-rule-sm);
  background: #fff;
  animation: tdf-sheet-in 0.25s both;
}

.tdf-navpanel[data-dark='true'][data-open='true'] {
  background: #0a0a0a;
  border-top-color: rgba(241, 240, 234, 0.22);
}

.tdf-navpanel[data-open='true'][data-open='true'] > a {
  display: flex;
  /* flex: none, or a short viewport crushes the rows instead of scrolling:
     44px glyphs in 52px rows, hairlines cutting through baselines. */
  flex: none;
  align-items: baseline;
  gap: 18px;
  padding: 22px var(--tdf-nav-inset, 18px);
  border-bottom: 1px solid var(--tdf-rule-sm);
  color: #0a0a0a;
  font-family: Archivo, sans-serif;
  font-weight: 600;
  font-size: clamp(30px, 7.5vw, 44px);
  line-height: 1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-decoration: none;
  animation: tdf-item-in 0.5s cubic-bezier(0.23, 1, 0.32, 1) both;
}

/* The block of destinations sits centred in a full-height sheet; in the
   desktop dropdown the sheet hugs its content and the auto margins resolve
   to zero, so one rule serves both. */
.tdf-navpanel[data-open='true'][data-open='true'] > a:first-of-type {
  margin-top: auto;
}

.tdf-navpanel[data-open='true'][data-open='true'] > a:not(.tdf-navpanel-cta)::before {
  counter-increment: tdfnav;
  content: counter(tdfnav, decimal-leading-zero);
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  /* 5.5:1 on the white sheet; the dark sheet swaps in its own muted ivory. */
  color: #5c5a54;
  min-width: 2.5ch;
}

.tdf-navpanel[data-dark='true'][data-open='true'] > a:not(.tdf-navpanel-cta)::before {
  color: #8f8d85;
}

.tdf-navpanel[data-open='true'][data-open='true'] > a:nth-of-type(1) { animation-delay: 0.08s; }
.tdf-navpanel[data-open='true'][data-open='true'] > a:nth-of-type(2) { animation-delay: 0.13s; }
.tdf-navpanel[data-open='true'][data-open='true'] > a:nth-of-type(3) { animation-delay: 0.18s; }
.tdf-navpanel[data-open='true'][data-open='true'] > a:nth-of-type(4) { animation-delay: 0.23s; }
.tdf-navpanel[data-open='true'][data-open='true'] > a:nth-of-type(5) { animation-delay: 0.28s; }
.tdf-navpanel[data-open='true'][data-open='true'] > a:nth-of-type(6) { animation-delay: 0.33s; }

.tdf-navpanel[data-dark='true'][data-open='true'] > a {
  color: #f1f0ea;
  border-bottom-color: rgba(241, 240, 234, 0.16);
}

/* The page you are on: its index number takes the accent, the way the contact
   button takes it on hover. */
.tdf-navpanel[data-open='true'][data-open='true'] > a[aria-current='page']::before {
  color: #6f58ff;
}

.tdf-navpanel[data-dark='true'][data-open='true'] > a[aria-current='page']::before {
  /* The accent, brought up to ≈7:1 on the dark sheet; #6f58ff is 4.26:1
     there, under AA for a 10.5px number. */
  color: #9c8bff;
}

/* The call to action keeps its small-control voice against the display-size
   index above it. */
.tdf-navpanel[data-open='true'][data-open='true'] > a.tdf-navpanel-cta {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  margin: 26px var(--tdf-nav-inset, 18px) 0;
  padding: 15px 22px;
  border: 1px solid rgba(10, 10, 10, 0.35);
  background: transparent;
  color: #0a0a0a;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
}

.tdf-navpanel[data-dark='true'][data-open='true'] > a.tdf-navpanel-cta {
  border-color: rgba(241, 240, 234, 0.35);
  color: #f1f0ea;
}

.tdf-navpanel[data-open='true'][data-open='true'] .tdf-navpanel-foot {
  display: flex;
  flex: none;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 22px;
  margin-top: auto;
  padding: 20px var(--tdf-nav-inset, 18px) calc(20px + env(safe-area-inset-bottom, 0px));
  animation: tdf-item-in 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0.36s both;
}

.tdf-navpanel-foot a {
  color: #0a0a0a;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-decoration: underline;
  text-underline-offset: 3px;
  word-break: break-all;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.tdf-navpanel-foot span {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.18em;
  color: #5c5a54;
}

.tdf-navpanel[data-dark='true'] .tdf-navpanel-foot span {
  color: #8f8d85;
}

.tdf-navpanel[data-dark='true'] .tdf-navpanel-foot a {
  color: #f1f0ea;
}

/* ============================================================
   Tier 1 — below the width the desktop header needs
   ============================================================ */

@media (max-width: 1239px) {
  /* ---------- Header ---------- */

  /* The desktop nav is a single non-wrapping flex row; it is the dominant
     source of horizontal overflow. Replace it with the panel. */
  header nav[aria-label='Primary'],
  .tdf-hide-sm {
    display: none !important;
  }

  /* A fixed rail in the left margin works where the content is inset past it.
     Below this width the content is full bleed, so the rail becomes an overlay
     on top of the text — 118px of a 390px screen. */
  .tdf-fixed-rail {
    display: none !important;
  }

  header > div {
    padding-right: 0 !important;
  }

  .tdf-navbtn {
    display: flex !important;
    align-items: center;
    gap: 9px;
    margin-left: auto;
    height: 100%;
    min-height: 44px;
    padding: 0 16px;
    border: 0;
    border-left: 1px solid var(--tdf-rule-sm);
    background: transparent;
    color: inherit;
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    cursor: pointer;
  }

  /* ---------- Nav panel: full-screen below the breakpoint ---------- */

  /* The look of the open menu is defined once above; here it just takes the
     whole screen under the bar. --tdf-hdr is measured from the live header by
     mobile.js on open — 58-60px at rest, 48 condensed. !important where the
     data-always geometry sets the same property with more weight. */
  .tdf-navpanel[data-open='true'] {
    position: absolute !important;
    top: 100% !important;
    left: 0;
    right: 0;
    z-index: 69;
    /* Two pixels past the measurement, so no sliver of the page shows at
       the viewport's foot while the sheet is open. */
    height: calc(100dvh - var(--tdf-hdr, 59px) + 2px);
    max-height: none !important;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* ---------- Overflow safety ---------- */

  img, svg, canvas, video, iframe {
    max-width: 100%;
  }

  /* Inline pixel widths, tagged at build time, become fluid. */
  .tdf-fluid {
    width: auto !important;
    min-width: 0 !important;
    max-width: 100% !important;
  }

  /* Grid and flex children default to min-width:auto, which refuses to shrink
     below min-content and pushes the track past the viewport. */
  [style*='display: grid'] > *,
  [style*='display: flex'] > * {
    min-width: 0;
  }

  /* Content that is genuinely wide — engineering tables, blueprint plates —
     scrolls inside its own box instead of stretching the page. */
  .tdf-scrollx {
    max-width: 100% !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
  }

  tdf-showroom {
    display: block;
    max-width: 100%;
    min-width: 0;
  }
}

/* ============================================================
   Tier 2 — phone
   ============================================================ */

@media (max-width: 900px) {
  /* Multi-column grids collapse. minmax(0, 1fr) rather than a bare 1fr: 1fr
     floors at the item's min-content width, so a wide child (the showroom
     control bar) would force the track past the viewport anyway.

     The exclusion is wrapped in :where() so it costs no specificity. Written
     as a bare :not(.tdf-keep-cols) it took the class's weight, and this rule
     — which is only meant to be a floor — started outranking the two-up
     layouts below it and the discipline tiles in site.css. Both quietly went
     back to one column and the home page grew 739px with every check still
     reporting clean. */
  [style*='grid-template-columns']:not(:where(.tdf-keep-cols)) {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  /* Collapsing the template is not enough on its own. A child still carrying
     `grid-column: span 3` creates implicit columns beside the single explicit
     one, and the explicit track is then starved to 0px — which is exactly what
     happened to the F1-F5 grid: its intro cell spans 3, so two of the five
     discipline tiles rendered 0x0 and were invisible on every screen under
     1240px. In one column a span means nothing, so clear it. */
  [style*='grid-template-columns']:not(:where(.tdf-keep-cols)) > [style*='grid-column'] {
    grid-column: auto !important;
  }

  /* Tagged at build time: four or more cells, none longer than seven words,
     no artwork. Stacking those one per row turns a compact index into a column
     of near-empty rows — the home page's six-cell chapter list became 500px of
     them. Three across on anything wider than a small phone. */
  .tdf-grid-2up {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* An odd cell count leaves a hole in the last row, and because these cells
     carry their own ground the hole reads as a broken cell rather than as
     empty space. The footer's chapter index has seven. The last one runs the
     full width instead, which closes the grid. */
  .tdf-grid-2up > :last-child:nth-child(odd) {
    grid-column: 1 / -1 !important;
  }

  @media (min-width: 420px) {
    .tdf-grid-2up {
      grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    }

    .tdf-grid-2up > :last-child:nth-child(odd) {
      grid-column: auto !important;
    }

    .tdf-grid-2up > :last-child:nth-child(3n + 1) {
      grid-column: 1 / -1 !important;
    }
  }

  /* Flex rows wrap rather than push past the viewport — except a row that is a
     marker plus its text, where wrapping drops the bullet onto a line of its
     own. The roadmap had a stray "·" above every list item. */
  [style*='display: flex'] {
    flex-wrap: wrap;
  }

  .tdf-marker-row {
    flex-wrap: nowrap !important;
  }

  /* Single-line labels wrap instead of overflowing — but not a marquee, where
     nowrap is the mechanism rather than a layout accident. The seam ticker was
     wrapping to 112px inside a 36px clipped band, so two half-rows of it
     collided on every phone. Anything carrying its own animation is opted out. */
  [style*='white-space: nowrap']:not([style*='animation']) {
    white-space: normal !important;
  }

  /* The showroom builds its own DOM at runtime, so the build-time tagging never
     sees it. Its stage is already width:100%; these bring its 7.5-9.5px control
     labels up to a readable size and give them a real tap target. */
  /* !important because Home-v7 carries a copy of this rule in its own <style>
     block — the design package pulled these fixes back into the source — and
     that copy still says 40px. A later rule at equal specificity wins, so the
     source's stale duplicate was overriding the layer that owns this decision. */
  tdf-showroom button {
    font-size: 10.5px !important;
    min-height: 44px !important;
    padding: 9px 12px !important;
  }

  tdf-showroom span {
    font-size: 10px !important;
    letter-spacing: 0.1em !important;
  }

  /* 6.5-9.5px mono labels are unreadable on a phone. */
  .tdf-micro {
    font-size: 10.5px !important;
    letter-spacing: 0.1em !important;
  }

  /* The vertical folio rail stops being a rail at this width — it becomes a
     tall block above the content. */
  .tdf-folio-rail {
    display: none !important;
  }

  /* The framed-viewport inset eats usable width at phone sizes. */
  .tdf-frame {
    margin: 0 !important;
    border-left: 0 !important;
    border-right: 0 !important;
  }

  main,
  section,
  footer {
    max-width: 100vw;
  }
}

/* Very narrow phones. */
@media (max-width: 400px) {
  .tdf-navbtn {
    padding: 0 12px;
  }

  .tdf-navbtn-label {
    display: none;
  }
}

/* ============================================================
   Phone reading floor
   ============================================================ */

@media (max-width: 900px) {
  /* Prose the design sets at a desktop size — as low as 11.5px — brought up to
     something readable at arm's length. Tagged at build time by family and
     computed size, so mono micro-labels keep their own floor. */
  .tdf-read {
    font-size: 14.5px !important;
    line-height: 1.65 !important;
  }

  /* All-caps type tracked out past 0.08em is a label, not a sentence, and the
     prose floor above is wrong for it: at 14.5px these eyebrows and cross-links
     wrapped onto two rows and outweighed the headings they sat under. They get
     a smaller floor — enough to be legible at arm's length, not enough to
     compete — and the tracking is eased, because letter-spacing set for 10.5px
     opens up too far once the size goes up. */
  .tdf-label {
    font-size: 11.5px !important;
    line-height: 1.6 !important;
    letter-spacing: 0.12em !important;
  }

  /* The showroom's hint describes a mouse and a keyboard. Neither is present. */
  tdf-showroom .tdf-hint,
  tdf-showroom [data-hint] {
    display: none !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tdf-navbtn-bars::before,
  .tdf-navbtn-bars::after {
    transition: none;
  }
}

/* ============================================================
   Phone density
   ============================================================ */

@media (max-width: 900px) {
  /* Blocks the design holds at a full screen height. The interlude is the
     clearest case: seven words, 844px of screen, nothing else in it. Held at
     three fifths of the screen it is still unmistakably a pause — it still
     arrives with nothing above or below it in view — without costing a scroll
     of its own. Tagged at build time; only sparse panels carry the class, so a
     panel with a scene in it keeps its full height. */
  .tdf-panel-tall {
    min-height: 58svh !important;
    padding-top: clamp(40px, 9vw, 64px) !important;
    padding-bottom: clamp(40px, 9vw, 64px) !important;
  }
}

@media (max-width: 900px) {
  /* A short-labelled link list reads as a column of near-empty rows on a phone:
     the hero's chapter index is six two-word rows, each at the 44px touch
     floor, in a box 358px wide. Two columns halve it without taking anything
     below the floor. Tagged at build time by shape — four or more direct child
     links, none longer than three words. */
  .tdf-nav-cols {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* Its heading is not one of the cells. */
  .tdf-nav-cols > :not(a) {
    grid-column: 1 / -1 !important;
  }

  /* A hairline between the columns, so the pairs read as a table rather than as
     two lists that happen to sit side by side. Counted by type: the list has a
     heading before the links, so nth-child would pick the left column. */
  .tdf-nav-cols > a:nth-of-type(even) {
    border-left: 1px solid rgba(241, 240, 234, 0.14);
  }
}

/* A phone held sideways is 390px tall, and a six-item index at 44px a row fills
   it on its own. Three across, two down. */
@media (max-width: 900px) and (orientation: landscape) and (max-height: 500px) {
  .tdf-nav-cols {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
  }

  .tdf-nav-cols > a:nth-of-type(even) {
    border-left: 0;
  }

  .tdf-nav-cols > a:not(:nth-of-type(3n + 1)) {
    border-left: 1px solid rgba(241, 240, 234, 0.14);
  }
}

/* Chapter watermarks.

   The 150px outline numeral beside each chapter is set into a margin the
   desktop layout has and a phone does not. Below the breakpoint it lands on
   the heading it is numbering — on the roadmap, three of them stack across the
   intro and the notice bar — and runs off whichever edge it is nearest. It is
   decoration with no room left to sit in, and it is already aria-hidden, so
   taking it away costs nothing: the chapter number is printed again a line
   below as "01 / DISCOVERY".

   Held to the breakpoint where the layout gains its side margin back, not to
   the phone tier: at 1000px the numeral still crosses the text column. */
@media (max-width: 1239px) {
  .tdf-ghost-num {
    display: none !important;
  }
}

/* A phone on its side. The full-size entries would need 380px for four rows;
   step them down so the index plus the address fit a 390px-tall viewport
   without the sheet having to scroll. */
@media (max-height: 520px) {
  .tdf-navpanel[data-open='true'][data-open='true'] > a {
    font-size: clamp(20px, 6.5vh, 30px);
    padding-top: 12px;
    padding-bottom: 12px;
  }

  .tdf-navpanel[data-open='true'][data-open='true'] > a.tdf-navpanel-cta {
    margin-top: 14px;
    padding: 11px 16px;
  }

  .tdf-navpanel[data-open='true'][data-open='true'] .tdf-navpanel-foot {
    padding-top: 12px;
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  }
}

/* The desktop sheet. The phone-size cap left each 1440px-wide row a small
   label hugging the left edge of an empty field, and the sheet's foot sat on
   the page with no closing edge — menu and page reading as one surface. */
@media (min-width: 1240px) {
  .tdf-navpanel[data-open='true'][data-open='true'] > a {
    font-size: clamp(44px, 4.6vw, 66px);
    padding-top: 28px;
    padding-bottom: 28px;
  }

  .tdf-navpanel[data-always='true'][data-open='true'] {
    border-bottom: 1px solid rgba(10, 10, 10, 0.2);
  }

  .tdf-navpanel[data-dark='true'][data-always='true'][data-open='true'] {
    border-bottom-color: rgba(241, 240, 234, 0.22);
  }
}

/* The full-screen index's entrance. Flipping the panel to display re-renders
   it, and CSS animations restart on render — so the choreography needs no
   JavaScript timing at all. */
@keyframes tdf-sheet-in {
  from { opacity: 0; }
}

@keyframes tdf-item-in {
  from {
    opacity: 0;
    transform: translateY(26px);
  }
}


@media (prefers-reduced-motion: reduce) {
  .tdf-navpanel,
  .tdf-navpanel > * {
    animation: none !important;
  }
}

/* ============================================================
   Tier-1 polish, phone share — tags from build step 2c-6
   ============================================================ */

@media (max-width: 900px) {
  /* A stacked side rail announces itself as a new block instead of butting
     against the paragraph above at the grid's 16px gap. Neutral rule tone,
     legible on the dark chapters and the light dossiers alike. */
  .tdf-rail {
    margin-top: 30px !important;
    padding-top: 20px !important;
    border-top: 1px solid rgba(127, 127, 125, 0.35) !important;
  }

  /* The blueprint's hover readout is a pointer affordance; frozen on a phone
     it sat on top of the plate caption. */
  .tdf-chip {
    display: none !important;
  }

  /* The inline address line duplicates the DIRECT rail one screen later. */
  .tdf-dup-sm {
    display: none !important;
  }

  /* The closing destination at phone scale. */
  .tdf-next {
    padding: 44px 22px 52px;
  }

  .tdf-next-title {
    font-size: clamp(32px, 9.5vw, 44px);
  }
}

/* Paired call-to-action buttons stack at one shared width with centred
   labels, instead of two left-hugging boxes with a lopsided rag. */
@media (max-width: 600px) {
  .tdf-cta-row {
    flex-direction: column !important;
    align-items: stretch !important;
    max-width: 420px;
  }

  .tdf-cta-row > a {
    justify-content: center !important;
    width: 100% !important;
  }
}

/* The hero headline broke into six lines with 'systems' stranded alone;
   text-wrap:balance gives up above its line limit. A step down breaks it
   into fuller lines. */
@media (max-width: 480px) {
  main > section:first-child h1 {
    font-size: 34px !important;
    max-width: 12ch !important;
  }
}
