/* The homepage's own CSS. Load after bundle.css. Tokens only: no new colours, radii, shadows or fonts
   (START-HERE.md). The responsive fixes at the end belong in bundle.css (BoardHero, SiteHeader, Tile)
   once the design system takes them. */

/* ── type helpers ───────────────────────────────────── */
.fl-p code { font: 400 0.9em/1 var(--font-mono); color: inherit; }
.fl-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ── product tiles: the whole tile is the link, like a FileRow. A card that links takes the sweep
   outline on hover (fl-tile--sweep, bundle.css) and lights its button (fl-sweep-host). ── */
.fl-product { position: relative; gap: var(--space-16); }
.fl-product .fl-h3 a { color: inherit; text-decoration: none; }
.fl-product .fl-h3 a::after { content: ""; position: absolute; inset: 0; }
/* a product that isn't out yet has no link, so no fl-tile--sweep and no hover */

/* The icon with the name on its right. Each icon is the family pack's: its body is 824/1024 of the
   image, so the image hangs 10px out to the left and the body lines up with the card's text.
   Every card uses its app's animated icon (the family pack's animated-icon SVGs, 10 Nov 2026), which
   loops on its own and holds still under prefers-reduced-motion. */
.fl-product__top { display: flex; align-items: center; gap: var(--space-14); width: 100%; }
.fl-product__icon { flex: none; display: block; width: 100px; height: 100px; margin: -10px 0 -10px -10px; }
.fl-product__name { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-10); }
.fl-product .fl-product__name .fl-h3 { margin: 0; font-size: 21px; letter-spacing: -0.02em; }
.fl-product__tags { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-8) var(--space-12); }
/* Under 360px a 100px icon leaves "Hyper Widgets" 134px of the 156px it needs: shrink the icon a little. */
@media (max-width: 359px) {
  .fl-product__top { gap: var(--space-12); }
  .fl-product__icon { width: 76px; height: 76px; margin: -7px 0 -7px -7px; }
}

/* The one-liner: each app's own headline, from its site (owner, 10 Nov 2026), above the Why. */
.fl-product__line { margin: 0; font: 600 18px/1.35 var(--font-head); letter-spacing: -0.01em; color: var(--fg); text-wrap: balance; }

/* Why: the frustration, recessed in a well (card) so it reads apart from what the app does. */
.fl-why { box-sizing: border-box; width: 100%; display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-14) var(--space-16); background: var(--card); }
.fl-why p { margin: 0; color: var(--fg); font-weight: 500; }

/* The card's foot: the badges, then the tickets, above a hairline; it sits at the bottom of the card. */
.fl-product__foot { box-sizing: border-box; width: 100%; margin-top: auto; display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-14) var(--space-16); padding-top: var(--space-16); border-top: 1px solid var(--line); }
.fl-product__deal { min-width: 0; display: flex; flex-direction: column; gap: var(--space-14); }
/* The button sits beside the badges and tickets when they fit (about 410px); when it can't, it spans the foot. */
.fl-product__foot { container-type: inline-size; }
@container (max-width: 420px) { .fl-product__foot .fl-product__cta { flex: 1 1 100%; justify-content: center; } }

/* Badges (UI kit › Tags and badges › F): the latest version in ink, Beta in a dashed box, then
   Changelog with a red cell while a release is new. The Changelog link sits above the card's own link. */
.fl-badges { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-10) var(--space-16); }
.fl-badge { display: inline-flex; align-items: center; gap: var(--space-8); font: 500 12px/1 var(--font-mono); color: var(--fg); }
a.fl-badge { position: relative; z-index: 1; padding-block: 6px; margin-block: -6px; text-decoration: none; } /* a 24px tap target, same look */
a.fl-badge:hover { text-decoration: underline; text-underline-offset: 3px; }
.fl-badge__new { flex: none; width: 6px; height: 6px; background: var(--fume); }
.fl-badge--ver { height: 20px; padding: 0 7px; background: var(--fg); color: var(--bg); font-size: 11px; font-variant-numeric: tabular-nums; }
.fl-badge--beta { box-sizing: border-box; height: 20px; padding: 0 7px; border: 1px dashed var(--muted); color: var(--muted); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; }
.fl-badge[hidden], .fl-badge__new[hidden] { display: none; }

/* Tickets (UI kit › Tags and badges › C): a punched stub with its number, torn along the dashes.
   Here the stub is a price or a release month, in the ticket's own colour (owner, 9 Nov: no red prices). */
.fl-tickets { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.fl-ticket { display: inline-flex; align-items: stretch; height: 30px; background: var(--fg); color: var(--bg); font: 500 11px/1 var(--font-mono); letter-spacing: 0.06em; text-transform: uppercase;
  -webkit-mask: radial-gradient(circle 4px at 0 50%, transparent 97%, black) left / 51% 100% no-repeat, radial-gradient(circle 4px at 100% 50%, transparent 97%, black) right / 51% 100% no-repeat;
  mask: radial-gradient(circle 4px at 0 50%, transparent 97%, black) left / 51% 100% no-repeat, radial-gradient(circle 4px at 100% 50%, transparent 97%, black) right / 51% 100% no-repeat; }
.fl-ticket__stub { display: flex; align-items: center; padding: 0 9px 0 12px; font-size: 12px; letter-spacing: 0.02em; font-variant-numeric: tabular-nums; }
.fl-ticket__label { display: flex; align-items: center; padding: 0 12px 0 9px; border-left: 1.5px dashed color-mix(in srgb, var(--bg) 45%, transparent); }

/* The card's button never shrinks; it takes the sweep (bundle.css), driven by the card's hover. */
.fl-product__cta { flex: none; }

/* ── design page (/design/) ─────────────────────────── */
.ds-hero__copy { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-18); }
.ds-hero__copy > * { margin: 0; }
.ds-note { margin: var(--space-22) 0 0; }
.ds-note a { color: var(--fg); }
.ds-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-12) var(--space-22); }
.ds-row--tight { gap: var(--space-8); }
.ds-flush { margin: 0; }
.ds-hint { font: 500 12px/1 var(--font-mono); color: var(--muted); }

/* the mark: plates, sizes, the app icon and the header lockup */
.ds-marks { display: flex; flex-direction: column; gap: var(--space-16); margin-top: var(--space-16); }
.ds-marks .fl-plate { min-height: 150px; }
.ds-marks__row { display: flex; flex-wrap: wrap; gap: var(--space-16); }
.ds-marks__row > * { flex: 1 1 200px; min-width: 0; }
.ds-sizes { display: flex; align-items: flex-end; justify-content: center; gap: var(--space-22); padding: var(--space-22); background: var(--panel); border: 1px solid var(--line); }
.ds-sizes figure { margin: 0; display: flex; flex-direction: column; align-items: center; gap: var(--space-8); }
.ds-marks__cell { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-12); padding: var(--space-16); }
.ds-marks__cell .fl-appicon { width: 72px; height: 72px; }
.ds-marks__cell .fl-appicon .fl-mark { --fl-size: 47px; }
.ds-marks__cell--panel { background: var(--panel); border: 1px solid var(--line); }

/* colour swatches */
.ds-swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-10); }
.ds-swatch { margin: 0; min-width: 0; background: var(--panel); border: 1px solid var(--line); }
.ds-swatch i { display: block; height: 88px; border-bottom: 1px solid var(--line); }
.ds-swatch figcaption { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-12) var(--space-14) var(--space-14); }
.ds-swatch b { font: 600 15px/1.3 var(--font-head); }
.ds-swatch code { font: 400 12px/1.4 var(--font-mono); color: var(--muted); font-variant-numeric: tabular-nums; }
.ds-swatch > figcaption > span { font-size: 13px; line-height: 1.45; color: var(--muted); }

/* type specimens */
.ds-type { border-top: 1px solid var(--line); }
.ds-type__row { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: var(--space-24); align-items: baseline; padding: var(--space-22) 0; border-bottom: 1px solid var(--line); }
.ds-type__meta b { display: block; font: 500 13px/1.3 var(--font-mono); }
.ds-type__meta span { display: block; margin-top: var(--space-4); font-size: 13px; color: var(--muted); }
.ds-type__sample { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.ds-type__sample--head { font: 600 clamp(28px, 4.2vw, 44px)/1.1 var(--font-head); letter-spacing: -0.02em; text-wrap: balance; }
.ds-type__sample--body { max-width: var(--size-measure); font: 400 18px/1.5 var(--font-body); color: var(--muted); }
.ds-type__sample--mono { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-12) var(--space-28); }
.ds-type__sample--word { font: 500 clamp(22px, 3vw, 30px)/1 var(--font-word); letter-spacing: -0.02em; }

/* component specimens: a caption bar on panel, the live component on the page ground */
.ds-specs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-flow: row dense; gap: var(--space-16); }
.ds-spec { margin: 0; min-width: 0; display: flex; flex-direction: column; border: 1px solid var(--line); }
.ds-spec--wide { grid-column: 1 / -1; }
.ds-spec__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-4) var(--space-16); padding: var(--space-14) var(--space-20); background: var(--panel); border-bottom: 1px solid var(--line); }
.ds-spec__head b { font: 600 15px/1.3 var(--font-head); }
.ds-spec__head span { font-size: 13px; color: var(--muted); }
.ds-spec__body { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: var(--space-16); padding: var(--space-24); }
.ds-spec__body > .fl-seg { align-self: flex-start; }
.ds-files.fl-files { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* the UI kit: each board is a mock from 03-ui-mocks, drawn live by kit.js for the current theme */
.ds-kit { display: flex; flex-direction: column; gap: var(--space-14); }
.ds-kit + .ds-kit { margin-top: var(--space-40); }
.ds-kit__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-4) var(--space-16); }
.ds-kit__head .fl-h3 { margin: 0; }
.kit-board { min-height: 160px; overflow-x: auto; }
.kit-board[aria-busy="true"] { background: var(--panel); border: 1px solid var(--line); }
.kit-board--failed { display: grid; place-items: center; padding: var(--space-24); border: 1px dashed var(--line); color: var(--muted); }

@media (max-width: 860px) {
  .ds-swatches { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ds-specs { grid-template-columns: minmax(0, 1fr); }
  .ds-tiles.fl-tiles--3 { grid-template-columns: minmax(0, 1fr); }
  .ds-files.fl-files { grid-template-columns: minmax(0, 1fr); }
  /* the boards were drawn two columns wide on a 1440px canvas: stack them on narrow screens */
  .kit-board > [data-theme] { grid-template-columns: minmax(0, 1fr) !important; padding: var(--space-20) !important; }
  .kit-board > [data-theme] > * { grid-row: auto !important; grid-column: auto !important; }
}
@media (max-width: 720px) {
  .ds-type__row { grid-template-columns: minmax(0, 1fr); gap: var(--space-10); }
}
/* Phones: the boards with rows drawn wider than a phone (the mocks are inline-styled, so these match
   their style attributes, scoped to each board). Nothing in a board scrolls sideways except
   Navigation's tab bar, which scrolls like tabs on a phone. */
@media (max-width: 560px) {
  /* Feedback · toasts: the log takes the width, its buttons go under it, and each toast drops the
     timestamp and wraps its message so the whole line reads */
  #kit-feedback div:has(> [style*="width: 452px"]) { flex-wrap: wrap !important; }
  #kit-feedback [style*="width: 452px"] { flex: 1 1 100% !important; width: 100% !important; min-width: 0; }
  #kit-feedback [style*="width: 452px"] > div { height: auto !important; min-height: 40px; padding-top: 9px !important; padding-bottom: 9px !important; }
  #kit-feedback [style*="width: 452px"] > div > span:first-child { display: none; }
  #kit-feedback [style*="width: 452px"] [style*="white-space: nowrap"] { white-space: normal !important; line-height: 1.35; overflow-wrap: anywhere; }
  /* Feedback · empty state: the atom stacks over the words, and the two buttons wrap */
  #kit-feedback [style*="border: 1px dashed var(--muted)"][style*="gap: 24px"] { flex-direction: column; align-items: flex-start !important; gap: 16px !important; padding: 18px !important; }
  #kit-feedback div:has(> button + button) { flex-wrap: wrap !important; }
  /* Feedback · banners: the action goes under the message, so the message keeps its width */
  #kit-feedback [style*="min-height: 46px"] { display: grid !important; grid-template-columns: 46px 60px minmax(0, 1fr); }
  #kit-feedback [style*="min-height: 46px"] > :nth-child(1), #kit-feedback [style*="min-height: 46px"] > :nth-child(2) { grid-row: 1 / span 2; }
  #kit-feedback [style*="min-height: 46px"] > :nth-child(3) { padding-bottom: 4px !important; }
  #kit-feedback [style*="min-height: 46px"] > :nth-child(4) { grid-column: 3; padding-bottom: 10px; }
  /* Feedback · skeleton: the drawing scales to the width */
  #kit-feedback svg[viewBox] { max-width: 100%; height: auto; }
  /* Navigation: the tab bar scrolls on its own */
  #kit-navigation [role="tablist"] { overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
  #kit-navigation [role="tablist"] > * { flex: none; }
  /* Fields and menus: the six code digits share the row */
  #kit-inputs input[inputmode="numeric"] { width: auto !important; flex: 1 1 0; min-width: 0; }
  /* Toggles: the inchworm's four states wrap */
  #kit-toggles [aria-hidden="true"][style*="gap: 18px"] { flex-wrap: wrap !important; }
  /* Checkboxes: the three board tiles stack */
  #kit-checkboxes div:has(> .kit-checkboxes-tile) { grid-template-columns: minmax(0, 1fr) !important; }
  /* Specimens and the sizes row keep more of a phone's width for what they show */
  .ds-spec__head { padding: var(--space-12) var(--space-16); }
  .ds-spec__body { padding: var(--space-16); }
  .ds-sizes { gap: var(--space-14); padding: var(--space-16); }
}

/* footer links: a 24px tap target on phones, same look */
.fl-footer a { display: inline-block; padding-block: 4px; }
/* "Designed by Frustrated Labs": the UI kit's made-by badge (Tags and badges › F), the mark in 12px
   cells, linking to the design system (owner, 10 Nov 2026). */
.fl-madeby { display: inline-flex !important; align-items: center; gap: 6px; vertical-align: bottom; text-decoration: none; }
.fl-madeby:hover { text-decoration: underline; text-underline-offset: 3px; }
.fl-madeby svg { flex: none; }
.fl-madeby .ink { fill: var(--fg); }
.fl-madeby .red { fill: var(--fume); }
/* The footer in two parts: the copyright and email on the left, the made-by badge on the right
   (owner, 10 Nov 2026). When a phone wraps it, the badge keeps to the right on its own line. */
.fl-footer--split { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-4) var(--space-24); }
.fl-footer--split .fl-madeby { margin-left: auto; }

/* ── about ──────────────────────────────────────────── */
.fl-about { max-width: var(--size-measure); }

/* ── theme switch glyphs (shown on phones, where the words don't fit) ── */
.fl-seg__glyph { display: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ── responsive ─────────────────────────────────────── */

/* The copy column is 600px, not 540px, so "Frustration-driven" holds one line at 64px. */
.fl-hero__copy { max-width: 600px; }

/* Board hero, side by side from 961px: the cells shrink with the window, so the board never reaches
   the words. */
@media (min-width: 961px) {
  .fl-hero--board { min-height: 520px; padding-block: 72px 88px; }
  .fl-board {
    --reach: min(var(--space-96), max(var(--space-24), (100vw - var(--size-container)) / 2 + var(--space-24)));
    --cell: clamp(28px, (min(100vw, var(--size-container)) - 2 * var(--space-24) + var(--reach) - 600px - var(--space-40) - var(--space-48)) / 9, 56px);
    position: absolute; top: calc(-1 * var(--space-96)); right: calc(-1 * var(--reach)); width: auto; margin: 0;
    grid-template-columns: repeat(9, var(--cell)); grid-auto-rows: var(--cell);
  }
  .fl-board > i:not([class]) { aspect-ratio: auto; }
  .fl-board__logo frustrated-logo { --fl-size: min(150px, 3 * var(--cell) - 12px); }
}

/* Board hero, stacked up to 960px: a full-width strip under the words, instead of a 552px block against
   the right edge. Same 72 cells and the same pieces: 18 × 4 on tablets, 12 × 6 on phones. */
@media (max-width: 960px) {
  .fl-board { width: 100%; margin: var(--space-40) 0 0; grid-template-columns: repeat(18, minmax(0, 1fr)); }
  .fl-board > .is-ink { grid-area: 1 / 2 / span 4 / span 3; }
  .fl-board > .is-fume { grid-area: 1 / 7 / span 3 / span 1; }
  .fl-board > .is-line { grid-area: 1 / 16 / span 2 / span 2; }
  .fl-board__logo { grid-area: 2 / 11 / span 3 / span 3; }
  .fl-board__logo frustrated-logo { --fl-size: min(150px, (100vw - 2 * var(--space-24)) / 7.5); }
}

/* Header: the nav sits on the right, beside the theme switch (owner, 10 Nov 2026). Under 960px it
   moves to its own row (bundle.css), where this has no effect. */
.fl-header .fl-nav { margin-left: auto; }

/* Header: keep the theme switch at every width. */
@media (max-width: 860px) {
  .fl-header .fl-seg { display: inline-flex; }
}

/* Product cards go one up before their text gets cramped. */
@media (max-width: 720px) {
  .fl-duo { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
  .fl-header__bar { column-gap: var(--space-12); }
  .fl-header__end { display: flex; }
  .fl-seg button { display: grid; place-items: center; padding: 7px var(--space-8); }
  .fl-seg__glyph { display: block; }
  .fl-seg__label { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .fl-board { gap: var(--space-4); grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .fl-board > .is-ink { grid-area: 2 / 2 / span 4 / span 3; }
  .fl-board > .is-fume { grid-area: 1 / 6 / span 3 / span 1; }
  .fl-board > .is-line { grid-area: 1 / 11 / span 2 / span 2; }
  .fl-board__logo { grid-area: 3 / 8 / span 3 / span 3; }
  .fl-board__logo frustrated-logo { --fl-size: calc((100vw - 2 * var(--space-16)) / 5); }
}

@media (max-width: 374px) {
  .fl-brand { font-size: 15px; gap: var(--space-10); }
}
/* At 320px the wordmark and the switch can't share a row: show the mark alone (its label still names it). */
@media (max-width: 349px) {
  .fl-brand { font-size: 0; gap: 0; }
}

