/* ==========================================================================
   Lightmorphic style - the one style sheet
   --------------------------------------------------------------------------
   The whole look of the app or site lives in this file. To change the look,
   change the settings in sections 1 to 3; everything below them uses those
   settings, so it follows on its own. Nothing else in the project sets a
   colour, size or font.

   1 Colours            the page, cards, text, highlight colour, states
   2 Font and sizes     the font file and every text size
   3 Shapes and space   corner rounding, gaps, page width
   4 Page layout        side bar app shell, website bar, bento puzzle, footer
   5 Parts              buttons, typing boxes, lists, menus, labels and more

   HOW EVERY SCREEN IS BUILT (copy example-settings.html)
   1 A title and one headline sentence saying what matters now.
   2 Cards in a puzzle (<div class="puzzle"> with bento.js), never a column
     of full-width cards. Two to four related things per card.
   3 Every card a box: at most twice as wide as it is tall, or twice as
     tall as it is wide (4 by 2, or 2 by 4). Never a long thin bar.
   4 Colour on every card: a tile-head with its icon in a circle, and a
     hue-* class. Numbers big and in the card's hue.
   5 Pictures over words: draw what the page is about (a .picture tile),
     show amounts as rings, bars and big figures, not sentences.
   6 Short words. A setting is its name and one short line. Anything
     longer goes behind the i (a circle with the letter i on the card's
     heading): pressing it opens the words inside the card, which grows
     to fit, and pressing again shuts them.
   ========================================================================== */


/* ==========================================================================
   1 COLOURS
   ========================================================================== */

:root {
  color-scheme: dark;

  /* The page and what sits on it. Each layer is one step lighter than the
     one below and has its own visible edge. No shadows. */
  --bg: #121212;              /* the page itself, near black */
  --panel: #1f1f1f;           /* cards and tiles */
  --panel-border: #1f1f1f;    /* no visible edge round a card: same as the card */
  --control: var(--panel);    /* buttons, icon circles, badges: set by what they sit on, see below */
  --raised: #2c2c2c;          /* a box inside a card, the chosen tab, menus */
  --raised-border: #2c2c2c;   /* no visible edge round those either */
  --border: #2c2c2c;          /* thin lines between rows and sections */

  /* Typing boxes: darker than the card, with an edge you can always find. */
  --field: #121212;
  --field-border: #9e9d9e;

  /* Text. */
  --fg: #e5e5e5;              /* normal text */
  --muted-fg: #b3b3b3;        /* quieter text: hints, headings over lists */

  /* The highlight colour: the main button, the current page, things
     waiting. Brand yellow on Lightmorphic apps; otherwise the brand colour
     or the colour the person picked. The highlight colour picker changes
     only this line (and the two under it, worked out from it). */
  --accent: #fbc711;
  --accent-hover: #ddaf0f;    /* the highlight colour while pointed at */
  --on-accent: #111111;       /* text and icons on the highlight colour */
  --on-accent-soft: #e5e5e5;  /* text on the highlight colour's quiet fill: the normal text colour */

  /* Problems. Red only for failures and deletes that cannot be undone. */
  --shade-red: #ff8a80;       /* the three lighter shades of palette hues, for WORDS on dark grey (the raw hues are too dark to read) */
  --shade-green: #6ccb70;
  --shade-blue: #5ab0f6;
  --danger: var(--shade-red); /* red words under a box */

  /* How things are going: dots, rings, bars and badges. Never the
     highlight colour. */
  --state-good: #4bae4f;      /* running, up to date */
  --state-calm: #2295f1;      /* working normally, ready */
  --state-busy: #fe9700;      /* busy */
  --state-bad: #f34236;       /* stopped, failed */
  --state-quiet: #9e9d9e;     /* off, idle */
  --on-good-soft: var(--shade-green);
  --on-calm-soft: var(--shade-blue);

  /* The only shadow, for things that float over the page: menus, labels,
     windows, the open dropdown. Cards never have one. */
  --shadow-float: 0 0 0 1px rgba(0,0,0,.5), 0 10px 28px rgba(0,0,0,.55);
}

/* Colour for each card: every card's icon circle (and its big figure)
   takes one of the palette hues, so a page is never a grey mess. Give a
   card one class, e.g. <section class="hue-blue">. One hue per kind of
   thing, kept the same across the app. Never the highlight colour, never
   red unless it is about a failure. */
.hue-accent { --hue: var(--accent); }   /* a picture that follows the chosen highlight colour */
.hue-pink { --hue: #e8207e; }   .hue-purple { --hue: #9b26ae; }
.hue-deep-purple { --hue: #6639ab; } .hue-indigo { --hue: #3d51b4; }
.hue-blue { --hue: #2295f1; }   .hue-light-blue { --hue: #03a8f3; }
.hue-cyan { --hue: #00bcd3; }   .hue-teal { --hue: #019587; }
.hue-green { --hue: #4bae4f; }  .hue-light-green { --hue: #8ac248; }
.hue-lime { --hue: #cbdc38; }   .hue-orange { --hue: #fe9700; }
.hue-deep-orange { --hue: #ff5721; } .hue-brown { --hue: #795649; }
.hue-blue-grey { --hue: #607c8b; }  .hue-red { --hue: #f34236; }

/* No light theme: Charlie's apps are dark only. A client who asks for a light version gets one designed then, not a guess now. */


/* ==========================================================================
   2 FONT AND TEXT SIZES
   The font files and both licence files sit in fonts/ beside this sheet.
   Copy them from ~/Claude_Repos/trindle-sans/fonts/ and its top folder.
   ========================================================================== */

@font-face {
  font-family: "Trindle Sans";
  src: url("fonts/TrindleSans-Variable.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Trindle Sans";
  src: url("fonts/TrindleSans-Italic-Variable.woff2") format("woff2");
  font-weight: 100 900; font-style: italic; font-display: swap;
}

:root {
  --font: "Trindle Sans", system-ui, sans-serif;
  --text: 1rem;               /* normal text, 16px */
  --text-small: .875rem;      /* hints, labels, small print: never smaller */
  --text-label: .75rem;       /* only the floating labels on pointing */
  --text-legal: .75rem;       /* the legal block in a website footer, and chart labels: the one other small size */
  --title: 2.25rem;           /* the page title */
  --heading: 1.25rem;         /* a section heading */
  --card-heading: 1rem;        /* the heading at the top of a card, sentence case */
  --figure: 1.75rem;          /* a big number in a tile */
  /* Websites only. */
  --display: clamp(2.5rem, 5.4vw, 4.5rem);    /* the one headline in a website opening, 72px on a laptop */
  --display-2: clamp(2rem, 3.6vw, 3rem);      /* a website page's title */
  --display-3: clamp(1.75rem, 2.8vw, 2.5rem); /* a section heading on a website */
  --lead: 1.25rem;            /* the one plain line under a website headline */
  --fact: 1.25rem;            /* the key fact on a question */
}


/* ==========================================================================
   3 SHAPES AND SPACE
   ========================================================================== */

:root {
  --radius: 6px;              /* typing boxes, boxes on a card, menus */
  --card-radius: 8px;         /* cards and tiles */
  --gap: 8px;                 /* between cards and tiles */
  --min-gap: 12px;            /* the least space between ANY two things: nothing ever touches (Charlie, 6 October 2026) */
  --card-pad: 14px 16px;      /* inside a card */
  --page-pad: 24px;           /* between the page edge and its content */
  --page-width: 1200px;       /* websites: the width of the content */
  --sidebar-width: 230px;     /* apps: the labelled side bar */
  --button: 34px;             /* regular button: every round button is this wide and tall, every worded button this tall (Charlie, 6 October 2026) */
  --button-large: 44px;       /* the large button: a hero or other opening's main buttons, and nothing else */
  --tap: 44px;                /* the smallest thing a finger must hit */
  /* Websites only. */
  --section-gap: 96px;        /* between sections of a website page: never less than 64px */
  --pic-radius: 12px;         /* corners of pictures and screenshots */
  --demo-height: 352px;       /* the front page demo, so pressing a button never moves the page */
}


/* ==========================================================================
   4 PAGE LAYOUT
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font: 400 var(--text)/1.6 var(--font);
  font-optical-sizing: none;
}
h1, h2, h3 { margin: 0; line-height: 1.2; font-weight: 600; }
p { margin: 0 0 .75rem; }
/* Links never have an underline, anywhere (Charlie, 6 October 2026). They change colour when pointed at. In running text they are told apart by colour and a heavier weight. */
a { color: var(--fg); text-decoration: none; font-weight: 600; }
a:hover { color: var(--muted-fg); text-decoration: none; }   /* a slight shade of grey when pointed at, never yellow, never an underline */
img, svg { display: block; max-width: 100%; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.muted { color: var(--muted-fg); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }

/* The page title and its one headline sentence. */
.page-title { font-size: var(--title); font-weight: 500; letter-spacing: -.02em; }
.headline { color: var(--muted-fg); margin: 4px 0 20px; }
.headline .dot { display: none; } /* no dot before the headline: it looks like the update dot (Charlie, 6 October 2026) */
.section-title { font-size: var(--heading); margin: 28px 0 12px; }

/* Apps and admin screens: a labelled side bar, then the content using the
   whole window. */
.app { display: flex; min-height: 100vh; }
.sidebar {
  flex: 0 0 var(--sidebar-width); padding: 18px 10px;
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 2px;
}
.sidebar .search { margin: 0 0 10px; min-height: 34px; font-size: var(--text-small); }
.sidebar .group { margin: 14px 8px 4px; font-size: 13px; font-weight: 600; color: var(--muted-fg); }
.sidebar .brand { display: flex; align-items: center; gap: 10px;
  font-weight: 600; padding: 0 8px 18px; color: var(--fg); text-decoration: none; }
.sidebar a.item {
  display: flex; align-items: center; gap: 10px; padding: 5px 8px;
  border-radius: var(--radius); color: var(--muted-fg); text-decoration: none;
  border: 1px solid transparent; white-space: nowrap;
}
.sidebar a.item svg { width: 16px; height: 16px; }
.sidebar a.item:hover { border-color: var(--accent); }
.sidebar a.item[aria-current="page"] {
  background: var(--raised); border-color: var(--raised-border); color: var(--fg);
}
.app main { flex: 1; min-width: 0; padding: 20px var(--page-pad); position: relative; }
.topline { display: flex; align-items: center; gap: 8px; }
.topline .page-title { flex: 0 1 auto; }  /* the i sits right beside the title */
.topline { gap: var(--min-gap); }

/* Nothing touches. Two cards, a card and the page edge, a button and the
   text beside it, a label and its box: always at least --min-gap apart.
   Only words inside one paragraph run together. */
.card + .card, .puzzle > * + * { margin-top: 0; }
p + .btn, p + .btn-main, p + .icon-btn, .headline + .btn-main { margin-top: var(--min-gap); }
.btn + .btn, .btn + .btn-main, .btn-main + .btn, .icon-btn + .icon-btn { margin-left: var(--min-gap); }

/* Websites: content 1200px wide, centred. Every page, legal pages too. */
.wrap { max-width: calc(var(--page-width) + 2 * var(--page-pad));
  margin: 0 auto; padding: 0 var(--page-pad); }
.topnav {
  position: sticky; top: 0; z-index: 40;
  background: var(--bg);
}
.topnav .wrap { display: flex; align-items: center; gap: 24px; min-height: 60px; }
.topnav .brand { display: flex; align-items: center; gap: 10px;
  font-weight: 700; color: var(--fg); text-decoration: none; }
.topnav ul { display: flex; gap: 20px; list-style: none; margin: 0 0 0 auto; padding: 0; }
.topnav ul a { color: var(--fg); text-decoration: none; font-weight: 600; }
.topnav ul a:hover { color: var(--muted-fg); }
#all-apps { display: flex; align-items: center; } /* the Lightmorphic apps menu */

/* Bento puzzle: tiles of different sizes locked together. The packing
   script places them; below 700px they stack. */
.puzzle { position: relative; }
.puzzle > * { position: absolute; overflow: hidden; }
.puzzle.flow { display: flex; flex-direction: column; gap: var(--gap); }
.puzzle.flow > * { position: static; }
[data-grow] { display: flex; flex-direction: column; }
.stat .figure { display: block; font-size: var(--figure); font-weight: 600; line-height: 1.2;
  white-space: nowrap; }
.stat.sized { container-type: size; justify-content: space-between; }
.stat.sized .figure { font-size: clamp(36px, min(40cqh, 30cqw), 72px); line-height: 1; }
.more { display: none; }
.more.show { display: flex; }

/* A plain grid of cards made from data (one per site, one per container). */
.card-grid { display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* The main footer: the closing block, a CARD (Charlie, 6 October 2026), with something
   interesting that belongs to the site and one call to action. The legal block below is never a card. */
.closing { background: var(--panel); border-radius: var(--card-radius); text-align: center; padding: 56px 24px; margin-top: 64px; }
.closing h2 { font-size: 2.5rem; font-weight: 500; letter-spacing: -.025em; margin: 0 0 20px; }

/* Footer (websites only): the main footer is the closing block above (something interesting and a call to action); then only the legal block, on the page. No generic link-column footer. */
.site-footer { margin-top: 32px; padding-bottom: 32px; }   /* the legal block: straight on the page, no card (Charlie, 6 October 2026) */
.footer-legal { display: grid; grid-template-columns: 1fr auto; gap: 12px 32px; align-items: end;
  font-size: var(--text-legal); color: var(--muted-fg); }
.footer-legal a { color: var(--muted-fg); }
.footer-legal a:hover { color: var(--fg); }
.footer-legal p { margin: 0; }
.footer-legal nav { display: flex; flex-wrap: wrap; gap: 4px 18px; justify-content: flex-end; }
/* Row one: the company line and registered office on the left, in line with the extra links on the
   right (links that are not in the menu: releases, what's new, code, security, licence). Row two:
   "Page last updated" on the left, in line with the legal links on the right. */
.footer-legal .company { grid-column: 1; }  .footer-legal .extra { grid-column: 2; align-self: start; }
.footer-legal .updated { grid-column: 1; }  .footer-legal .legal { grid-column: 2; }


/* ==========================================================================
   5 PARTS
   ========================================================================== */

/* Card: flat, one step lighter than the page, with a visible edge. */
.card, .puzzle > * {
  background: var(--panel); border: 1px solid var(--panel-border);
  border-radius: var(--card-radius); padding: var(--card-pad);
}
.card-title { font-size: var(--card-heading); margin-bottom: 10px; font-weight: 600; color: var(--fg); }  /* sentence case, never capitals: capitals are not fashionable (Charlie, 6 October 2026) */
.card.clickable { cursor: pointer; transition: border-color .15s ease, background-color .15s ease; }
.card.clickable:hover { border-color: var(--accent); }

/* Controls go the OPPOSITE way to what they sit on (Charlie, 6 October
   2026): on a card or a box they are darker, not lighter, so they look sunk
   in rather than raised. On the page itself (the darkest step) they are one
   step lighter. Only floating things (menus, labels, the notice) stay light. */
.card, .puzzle > *, .panel { --control: var(--bg); }
.box { --control: var(--panel); }

/* A box inside a card. */
.box { background: var(--raised); border: 1px solid var(--raised-border);
  border-radius: var(--radius); padding: 10px 12px; }

/* The top of a card: its icon in a circle of the card's hue, then its
   name. Every card on a page has one. */
.tile-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.tile-head .card-title { margin: 0; }
/* Text and icons use the colour scheme only (Charlie, 6 October 2026):
   the icon circle is a grey box with a light icon, headings and figures
   are normal text. Only pictures keep colour: a card's hue colours its
   small pictures (below) and the main picture, nothing else. */
.icon-circle { background: var(--control); border-color: var(--raised); color: var(--fg); }

/* No decorative pictures (Charlie, 7 October 2026): dots, waves, chips and stacks that mean nothing were being copied into every card and made websites too colourful. A picture appears only where it shows something real: an amount, a state, the shape of the subject. A card with nothing to draw has no picture, and its icon stays grey. */

/* One setting: its name and one short line on the left, the control right
   beside it. Settings sit in cards of a few, and the cards go in a puzzle. */
.set { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding: 10px 0; }   /* no line between settings: space does the work. A control that has no room beside its words drops under them, never squeezing them into a thin column */
.set > div:first-child { flex: 1 1 16ch; min-width: 16ch; }
.set b { display: block; font-weight: 600; }
.set .sub { display: block; color: var(--muted-fg); font-size: var(--text-small); }
.set select, .set .select { width: auto; }

/* The i: a round button with the letter i on the card's heading. The long
   words sit inside a <details class="info">; the heading is its <summary>.
   Shut by default. Open, the words float OVER the card as an overlay (Charlie,
   6 October 2026): nothing is pushed down, no card grows, the puzzle does not
   pack again. Pressing the i again or Escape closes it. */
details.info { position: relative; }
details.info > summary { list-style: none; cursor: pointer; }
details.info > summary::-webkit-details-marker { display: none; }
details.info > summary .card-title { flex: 0 1 auto; }  /* the i sits right beside the word, not at the far edge */
details.info > summary.tile-head { gap: var(--min-gap); }
.i-btn { width: 24px; height: 24px; flex: none; display: inline-grid; place-items: center;
  border-radius: 50%; border: 1.5px solid var(--muted-fg); color: var(--muted-fg);
  font: 700 14px/1 var(--font); }
details.info > summary:hover .i-btn { border-color: var(--accent); color: var(--accent); }
details.info[open] .i-btn { background: var(--fg); border-color: var(--fg);
  color: var(--bg); }  /* open: a light circle, never yellow (it would look like the update dot) */
details.info > :not(summary) { position: absolute; left: 0; right: 0; top: calc(100% + 6px);
  z-index: 60; margin: 0; padding: 12px 14px; background: var(--raised); color: var(--fg);
  border-radius: var(--radius); box-shadow: var(--shadow-float); font-size: var(--text-small); }
.puzzle > *:has(details.info[open]), .card:has(details.info[open]) { overflow: visible; z-index: 30; }

/* A picture tile: the drawing of what the page is about grows to fill. */
.picture .pic { flex: 1; width: 100%; min-height: 150px; }
/* Paint for drawings, so an SVG never carries a colour of its own. Put a
   hue-* class on a shape (or its group) to colour it with that hue. */
.pic { font-family: var(--font); }
.pic .page   { fill: var(--bg); stroke: var(--panel-border); }
.pic .box    { fill: var(--raised); stroke: none; }
.pic .text   { fill: var(--fg); }
.pic .quiet  { fill: var(--muted-fg); }
.pic .lit    { fill: color-mix(in srgb, var(--accent) 14%, var(--panel)); stroke: var(--accent); }
.pic .lit-text { fill: var(--on-accent-soft); }
.pic [class*="hue-"] { fill: var(--hue); }
.pic .ring-track { fill: none; stroke: var(--hue); stroke-opacity: .35; }

/* Buttons: one size throughout (Charlie, 6 October 2026). Two sizes only:
   regular, --button (34px) tall: round icon buttons 34 by 34 with a 16px icon,
   worded buttons 34px tall with 14px bold words and 16px either side; and
   large, --button-large (44px), for a hero's buttons only: 16px words, 22px
   either side, 20px icon. Nothing in between. On touch screens each gets
   an invisible 44px tap area. Look: a grey circle (pill) that fills yellow
   when pointed at; the one main action is the yellow pill. No edges. */
.icon-btn, .btn-main, .btn {
  position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--button); border: 0; cursor: pointer; text-decoration: none; color: var(--fg);
  font: 700 var(--text-small)/1 var(--font);
  transition: background-color .15s ease, color .15s ease, transform .1s ease;
}
.icon-btn::before, .btn-main::before, .btn::before { content: ""; position: absolute; inset: -6px; } /* 44px to tap */
.icon-btn { width: var(--button); border-radius: 50%; background: var(--control); }
.icon-btn svg, .btn-main svg, .btn svg { width: 16px; height: 16px; }
.btn-main, .btn { padding: 0 16px; border-radius: 999px; background: var(--control); }
.btn-main, .btn.main { background: var(--accent); color: var(--on-accent); }   /* the one main action */
.icon-btn:hover, .btn:hover { background: var(--accent); color: var(--on-accent); }
/* Large: the only other size. Add class "large" to a hero's buttons. */
.icon-btn.large, .btn-main.large, .btn.large { height: var(--button-large); font-size: var(--text); }
.icon-btn.large { width: var(--button-large); }
.btn-main.large, .btn.large { padding: 0 22px; }
.icon-btn.large svg, .btn-main.large svg, .btn.large svg { width: 20px; height: 20px; }
.btn-main:hover, .btn.main:hover { background: var(--accent-hover); }
.icon-btn:active { transform: scale(.92); }
.icon-btn.armed { background: var(--accent); color: var(--on-accent); }

/* In a card, a box is as wide as its answer, never stretched to fill the
   card (Charlie, 6 October 2026: a first name must not get a 50 character
   box just because the card is wide). A card with spare room gets another
   box beside it, a picture or a fact, not longer boxes. Add class "fill"
   only to a box that really holds a sentence or more. */
.puzzle input:not([type="checkbox"]):not([type="radio"]):not(.fill),
.card input:not([type="checkbox"]):not([type="radio"]):not(.fill),
.puzzle select:not(.fill), .card select:not(.fill) { max-width: 32ch; }

/* Typing boxes. As wide as what goes in them: full width for sentences,
   short for short answers (add one of the size classes). */
label, .label-text { display: block; font-weight: 600; font-size: .9375rem; margin-bottom: 6px; }
input:not([type="checkbox"]):not([type="radio"]), textarea, select, .select {
  display: block; width: 100%; padding: 8px 10px; min-height: 38px;
  background: var(--field); color: var(--fg);
  border: 1px solid var(--field-border); border-radius: var(--radius);
  font: 400 var(--text)/1.4 var(--font);
}
textarea { min-height: 6rem; resize: vertical; }
/* A dropdown: the same height as a button, the words set properly (left
   aligned, centred up and down, never cut off at the top or bottom), a
   chevron on the right, long words trimmed with ... rather than wrapping.
   Use one only when the answers are long or many; see "Choosing one". */
select, .select { appearance: none; -webkit-appearance: none; height: var(--button); min-height: var(--button);
  padding: 0 34px 0 12px; line-height: calc(var(--button) - 2px); font-size: var(--text-small); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23b3b3b3' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; }
.size-code     { width: 10ch !important; }  /* a short code or a number */
.size-postcode { width: 12ch !important; }
.size-date     { width: 14ch !important; }
.size-phone    { width: 18ch !important; }
.hint { color: var(--muted-fg); font-size: var(--text-small); margin-top: 4px; }
.error-text { color: var(--danger); font-size: var(--text-small); margin-top: 6px; }
.form-row { display: flex; flex-wrap: wrap; gap: 12px 20px; }
.form-row > * { flex: 1 1 14rem; }
.form-row > .short { flex: 0 0 auto; }

/* Saved: the box glows in the highlight colour for a moment. */
@keyframes saved {
  0%, 100% { border-color: var(--field-border); box-shadow: none; }
  25%, 60% { border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent); }
}
.just-saved { animation: saved 1.6s ease; }

/* Switches: anything that turns a setting on or off. */
.switch { display: inline-flex; align-items: center; gap: 10px;
  min-height: var(--tap); cursor: pointer; font-weight: 400; margin: 0; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track { flex: none; width: 40px; height: 22px; position: relative;
  background: var(--raised); border: 1px solid var(--field-border); border-radius: 999px;
  transition: background-color .15s ease; }
.switch .track::after { content: ""; position: absolute; top: 3px; left: 3px;
  width: 14px; height: 14px; border-radius: 50%; background: var(--muted-fg);
  transition: transform .15s ease; }
.switch input:checked + .track { background: var(--accent); border-color: var(--accent); }
.switch input:checked + .track::after { transform: translateX(18px); background: var(--on-accent); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Ticks and choices. */
input[type="checkbox"], input[type="radio"] {
  appearance: none; margin: 0; flex: none; cursor: pointer;
  width: 20px; height: 20px; display: grid; place-items: center;
  background: var(--field); border: 1px solid var(--field-border);
}
input[type="checkbox"] { border-radius: 6px; }
input[type="radio"] { border-radius: 50%; }
input[type="checkbox"]:checked, input[type="radio"]:checked {
  background: var(--accent); border-color: var(--accent); }
input[type="checkbox"]:checked::after { content: ""; width: 9px; height: 5px;
  border-left: 2.5px solid var(--on-accent); border-bottom: 2.5px solid var(--on-accent);
  transform: translateY(-1px) rotate(-45deg); }
input[type="radio"]:checked::after { content: ""; width: 8px; height: 8px;
  border-radius: 50%; background: var(--on-accent); }
.choice { display: flex; align-items: center; gap: 10px; min-height: var(--tap);
  font-weight: 400; cursor: pointer; margin: 0; }

/* Lists and tables: no lines. Every second row is a slightly darker band (Charlie, 6 October 2026). */
.rows { width: 100%; overflow-x: auto; }
.rows .row { display: grid; grid-template-columns: var(--cols, 2fr 1fr);
  gap: 12px; align-items: center; padding: 9px 12px; border-radius: var(--radius); }
.rows .row:not(.head):nth-of-type(even) { background: var(--control); }
.rows .row.head { color: var(--muted-fg); font-size: var(--text-small); font-weight: 500; }
.rows .row.clickable { cursor: pointer; border-radius: 6px; }
.rows .row.clickable:hover { background: var(--raised); }
.rows .sub { display: block; color: var(--muted-fg); font-size: var(--text-small); }

/* Icons beside a heading or in a list sit in a circle. */
.icon-circle { width: 34px; height: 34px; flex: none; display: inline-grid; place-items: center;
  border-radius: 50%; background: var(--control); border: 1px solid var(--raised-border); }
.icon-circle svg { width: 16px; height: 16px; }

/* Tabs and the segmented choice: a dark strip, the chosen one a lighter box.
   The segmented choice (role radiogroup) is how to pick one of two to four
   short answers; it is the preferred way (Charlie, 6 October 2026). The strip
   is as tall as a regular button (34px). */
.tabs, .segmented { display: inline-flex; gap: 2px; padding: 3px; height: var(--button);
  background: var(--field); border: 0; border-radius: 999px; }
.tabs [role="tab"], .segmented [role="radio"] { height: 100%; padding: 0 14px; border: 0; border-radius: 999px;
  background: none; color: var(--muted-fg); font: 600 var(--text-small)/1 var(--font); cursor: pointer; white-space: nowrap; }
.tabs [role="tab"]:hover, .segmented [role="radio"]:hover { color: var(--fg); }
.tabs [role="tab"][aria-selected="true"], .segmented [role="radio"][aria-checked="true"] { background: var(--raised); color: var(--fg); }

/* Things that float: menus, the open dropdown list, windows, quick find. */
.float { background: var(--raised); border: 1px solid var(--raised-border);
  border-radius: 10px; box-shadow: var(--shadow-float); }
.menu { position: absolute; z-index: 30; min-width: 180px; padding: 5px; }
.menu [role="option"], .menu [role="menuitem"] { display: block; padding: 7px 10px;
  border-radius: 6px; cursor: pointer; }
.menu [role="option"]:hover, .menu [role="menuitem"]:hover { background: var(--panel); }
.menu [aria-selected="true"] { background: var(--accent); color: var(--on-accent); }
.menu .hot:not([aria-selected="true"]) { background: var(--panel); }
.menu .opts [role="option"] { height: 34px; display: flex; align-items: center; padding: 0 12px; white-space: nowrap; }
.menu .opts [role="option"][hidden] { display: none; }
.menu-search { margin-bottom: 4px; }
.menu-count { color: var(--muted-fg); font-size: var(--text-small); padding: 2px 12px 6px; min-height: 22px; }
.select .val { overflow: hidden; text-overflow: ellipsis; }
.select::after { content: ""; flex: none; width: 12px; height: 12px; margin-left: 10px; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b3b3b3' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat; }
.select { display: flex; align-items: center; justify-content: space-between; cursor: pointer; }
.window-backdrop { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: rgba(0,0,0,.55); }
.window { width: min(560px, 100% - 32px); padding: 20px; }

/* The floating label shown on pointing (a second and a half, then gone). */
.tip { position: absolute; top: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  white-space: nowrap; pointer-events: none; z-index: 50;
  font: 600 var(--text-label)/1 var(--font); padding: 5px 10px; border-radius: 999px;
  background: var(--raised); color: var(--fg); /* the box colour, solid, no edge */
  box-shadow: 0 4px 10px rgba(0,0,0,.45); }

/* Badges and state dots. */
.badge { display: inline-block; padding: 1px 9px; border-radius: 999px;
  font-size: var(--text-label); font-weight: 600; line-height: 1.6; }
/* The highlight colour picker (accent-picker.js): round swatches on one or
   two lines, then a box to type a brand colour. Round, solid, no edge; the
   chosen one has a light ring in the text colour. */
.swatches { display: grid; grid-template-columns: repeat(var(--per, 8), 28px); justify-content: space-between; gap: 8px 0;
  align-items: center; }  /* the same columns on both lines, so everything lines up and the block is a full rectangle; script sets --per and --span */
.swatch { width: 28px; height: 28px; border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  background: var(--sw); flex: none; }
.swatch[hidden] { display: none; }
.swatch.custom { cursor: default; background: var(--control); }  /* the colour typed in the box beside it; grey until one is typed */
.swatch.custom.on { background: linear-gradient(var(--sw), var(--sw)), repeating-conic-gradient(#5a5a5a 0 25%, #8a8a8a 0 50%) 50% / 10px 10px; }  /* a see-through colour shows over a check pattern */
.swatch[aria-checked="true"] { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--fg); }
.swatches input.hexbox { grid-column: span var(--span, 3); width: 100%; max-width: none; padding-inline: 6px; font-size: var(--text-small);  /* fills exactly the fewest whole columns that hold #RRGGBBAA, so no column is left empty */ min-height: 28px; padding-block: 3px; text-transform: uppercase; font-variant-numeric: tabular-nums; }

/* The notice (Charlie, 6 October 2026): a small pill fixed to the bottom
   centre of the WINDOW (the centre of the work area when there is a side bar), one line, 3 seconds, fades in and out. It is
   position: fixed, so it never takes space in the page and the page never
   moves, scrolls or jumps for it: not to the top, not to the bottom, nothing.
   Script must not call scrollIntoView, focus() or change scroll position
   to show it. It can carry one plain word to press (Undo). The page's
   answer to an action is still given where the person is looking first
   (the glow, the headline, the button); the notice is for what would
   otherwise go unseen. */
.notice { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  max-width: calc(100% - 32px); z-index: 80; display: flex; align-items: center; gap: var(--min-gap);
  background: var(--raised); color: var(--fg); border-radius: 999px; padding: 10px 18px;
  font: 600 var(--text-small)/1.3 var(--font); box-shadow: var(--shadow-float);
  opacity: 0; pointer-events: none; transition: opacity .25s ease; }
.notice.show { opacity: 1; pointer-events: auto; }
/* In an app with a side bar, centre it on the work area, not the whole window. */
.app ~ .notice, .app + .notice { left: calc(50% + var(--sidebar-width) / 2); }
.notice .bad { color: var(--shade-red); }          /* a failure starts with a short red word */
.notice button { background: none; border: 0; padding: 0; color: var(--fg);
  font: inherit; text-decoration: none; font-weight: 600; cursor: pointer; }
.notice button:hover { color: var(--muted-fg); }
@media (prefers-reduced-motion: reduce) { .notice { transition: none; } }

/* The bell (Charlie, 6 October 2026): top right, only for things that are
   important. Pointing shows the label "Last three notifications"; pressing
   opens a floating list of the last three beside it. No number, no
   red or yellow mark: it is only a record to re-read. The list floats over
   the page, so the page never moves. */
.bell-list { position: absolute; right: var(--page-pad); top: 56px; width: min(420px, calc(100% - 32px));
  background: var(--raised); border-radius: var(--card-radius); padding: 12px;
  box-shadow: var(--shadow-float); z-index: 70; }
.bell-list .item { display: flex; gap: var(--min-gap); align-items: flex-start;
  background: var(--panel); border-radius: var(--radius); padding: 10px 12px; margin-top: 6px; }

/* Badges: a grey pill with coloured words, no faded wash (Charlie, 6 October 2026).
   The colours are the lighter shades so the words pass the readability rule on grey. */
.badge { background: var(--control); color: var(--fg); }
.badge.waiting { color: var(--accent); }
.badge.good    { color: var(--shade-green); }
.badge.calm    { color: var(--shade-blue); }
.badge.bad     { color: var(--shade-red); }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); vertical-align: middle; }
.dot.good { background: var(--state-good); } .dot.calm { background: var(--state-calm); }
.dot.busy { background: var(--state-busy); } .dot.bad { background: var(--state-bad); }
.dot.quiet { background: var(--state-quiet); }

/* Progress: a bar, a spinning ring, numbered steps. */
.bar { height: 6px; border-radius: 3px; background: var(--control); overflow: hidden; }
.bar > span { display: block; height: 100%; background: var(--accent);
  width: calc(var(--value, 0) * 1%); } /* script sets --value, 0 to 100 */
/* One ring, one thickness: the progress ring and the spinner share the
   same line proportion and round ends at every size (Charlie, 6 October
   2026). Draw every ring as an SVG with viewBox 0 0 84 84 and a circle r=34 (so the thick line fits inside);
   its size is set here, so thickness scales with it. The spinner is the
   ring with a quarter of it filled, turning. */
.ring-sm, .spin { width: 44px; height: 44px; flex: none; }
.ring-sm { transform: rotate(-90deg); }
.ring-sm circle, .spin circle { fill: none; stroke-width: 15; stroke-linecap: round; }
.ring-sm .track, .spin .track { stroke: var(--panel); }
.ring-sm .fill, .spin .fill { stroke: var(--accent); }
.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.steps { display: flex; align-items: center; gap: 8px; list-style: none; margin: 0; padding: 0; }
.steps li { width: 28px; height: 28px; flex: none; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid var(--field-border); font-weight: 600; }
.steps li.done { background: var(--control); border-color: var(--raised-border); }
.steps li[aria-current="step"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.steps .join { flex: 1; height: 1px; width: auto; border: 0; border-radius: 0; background: var(--border); }

/* Dropping files to upload. */
.drop { border: 1.5px dashed var(--field-border); border-radius: var(--card-radius);
  padding: 18px; text-align: center; color: var(--muted-fg); }
.drop.over { border-color: var(--accent); }

/* Profile pictures. */
.avatar { width: 28px; height: 28px; border-radius: 50%; flex: none; object-fit: cover;
  display: inline-grid; place-items: center; font-size: var(--text-label); font-weight: 600;
  background: var(--raised); border: 1px solid var(--raised-border); }
.avatar.big { width: 40px; height: 40px; }

/* The update dot: the version, then the dot, top right. */
.update { position: absolute; top: 22px; right: var(--page-pad);
  display: flex; align-items: center; gap: 8px; }
.update .version { font-size: 12px; color: var(--muted-fg); }
.update .udot { position: relative; width: 16px; height: 16px; border-radius: 50%;
  border: 0; padding: 0; cursor: pointer; background: var(--state-good); }
.update .udot::before { content: ""; position: absolute; inset: -14px; } /* 44px to tap */
.update .udot.available { background: var(--accent); }
.update .udot.ready     { background: var(--state-calm); }
.update .udot.failed    { background: var(--state-bad); }
.update .udot.busy      { animation: beat 1s ease-in-out infinite; }
@keyframes beat { 50% { transform: scale(.75); opacity: .6; } }

/* Gentle motion when a page opens. */
.rise { animation: rise .28s ease-out both; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}


/* ==========================================================================
   5 PARTS, continued: this website (lightmorphic.com)
   Every rule below uses the settings in sections 1 to 3 only. Colour lives
   in pictures and nowhere else, and a page shows at most two colours
   besides the highlight and the greys (7 October 2026).
   ========================================================================== */

/* The two picture colours. They are worked out from the highlight, not
   chosen: the highlight is brand yellow, its opposite on the colour wheel is
   blue, and the neighbour of blue used when a second colour is truly needed
   is cyan (reference/colours.md). If the highlight is ever changed, change
   these two lines and nothing else. Neighbouring pictures alternate them. */
:root { --pic-1: #2295f1; --pic-2: #00bcd3; }
.pic-1 { --hue: var(--pic-1); }
.pic-2 { --hue: var(--pic-2); }
/* Pages not yet re-marked still say hue-green, hue-orange and the like.
   They now draw in the two picture colours, so nothing else shows. Delete
   these lines when those pages say pic-1 and pic-2 themselves. */
.hue-blue, .hue-orange, .hue-blue-grey { --hue: var(--pic-1); }
.hue-green { --hue: var(--pic-2); }

/* The spacing scale: 4, 8, 12, 16, 24, 32, 48, 64 (96 between big sections).
   The shared parts above still carry a few older numbers; where this site uses
   them they are brought onto the scale here. */
:root { --card-pad: 16px; }
.btn, .btn-main, .icon-btn { gap: 8px; }
.topnav .brand { gap: 8px; }
.footer-legal nav { gap: 4px 16px; }
.tile-head, .switch, .choice { gap: 12px; }
.card-title { margin-bottom: 12px; }
.set { gap: 8px 16px; padding: 12px 0; }
.badge { padding: 4px 12px; }
.box { padding: 12px; }
label, .label-text { margin-bottom: 8px; }
input:not([type="checkbox"]):not([type="radio"]), textarea, select, .select { padding: 8px 12px; }
.error-text { margin-top: 8px; }
.form-row { gap: 12px 24px; }
.tabs, .segmented { gap: 4px; padding: 4px; }
.tabs [role="tab"], .segmented [role="radio"] { padding: 0 16px; }
.menu { padding: 4px; }
.menu [role="option"], .menu [role="menuitem"] { padding: 8px 12px; }

/* Skip link: off screen until the keyboard reaches it. */
.skip { position: absolute; z-index: 90; left: var(--page-pad); top: -96px; }
.skip:focus { top: var(--min-gap); }

/* The top bar: fixed at the top while the page scrolls, no line under it.
   The current page is a lighter box; the apps menu is last on the right. */
.topnav .wrap { position: relative; gap: var(--min-gap); }
.topnav .brand { flex: none; margin-right: var(--min-gap); }
.topnav .brand img { width: 28px; height: 28px; }
.topnav ul { gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.topnav ul a { display: inline-flex; align-items: center; height: var(--button);
  padding: 0 var(--min-gap); border-radius: 999px; white-space: nowrap; }
.topnav ul a[aria-current="page"] { background: var(--raised); }
.topnav ul a[aria-current="page"]:hover { color: var(--fg); }
.topnav .menu-only { display: none; }
.topnav .nav-cta { flex: none; }
.topnav .menu-btn { display: none; }
.topnav .menu-btn[aria-expanded="true"] { background: var(--accent); color: var(--on-accent); }
@media (max-width: 1040px) {
  .topnav.menu-ready .brand { margin-right: auto; }
  .topnav.menu-ready .menu-btn { display: inline-flex; }
  .topnav.menu-ready ul { display: none; }
  .topnav.menu-ready.open ul { display: flex; flex-direction: column; align-items: stretch;
    position: absolute; top: 100%; right: var(--page-pad); z-index: 50;
    min-width: 224px; padding: 8px; background: var(--raised); border-radius: var(--card-radius);
    box-shadow: var(--shadow-float); }
  .topnav.menu-ready.open ul a { width: 100%; }
  .topnav.menu-ready.open ul a[aria-current="page"] { background: var(--panel); }
}
@media (max-width: 620px) {
  .topnav .nav-cta { display: none; }
  .topnav .menu-only { display: list-item; list-style: none; }
}

/* Sections: space between them, never a card on a card. */
.band { margin-top: var(--section-gap); }
.band.first { margin-top: 48px; }
.band-head { display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--min-gap) 32px; flex-wrap: wrap; margin-bottom: 24px; }
.band-head > div { flex: 1 1 28rem; }
.band-title, .split h2 { font-size: var(--display-3); font-weight: 500; letter-spacing: -.02em; line-height: 1.1; }
.band-lead { color: var(--muted-fg); font-size: var(--lead); margin: var(--min-gap) 0 0; }
.band-head .btn { margin: 0; }

/* A page's opening: its title and one plain line. */
.page-head { padding-top: 48px; }
.page-head h1 { font-size: var(--display-2); font-weight: 500; letter-spacing: -.02em; line-height: 1.1; }
.page-head .lead { color: var(--muted-fg); font-size: var(--lead); margin: 16px 0 0; }
.page-head .lead b { color: var(--fg); font-weight: 600; }

/* The front page opening: a centred headline over the product in a window. */
.hero { text-align: center; padding-top: 48px; }
.hero h1 { font-size: var(--display); font-weight: 500; letter-spacing: -.03em; line-height: 1.05;
  max-width: 13em; margin: 0 auto 24px; }
.hero .lead { font-size: var(--lead); color: var(--muted-fg); max-width: 46em; margin: 0 auto 32px; }
.actions { display: flex; gap: var(--min-gap); flex-wrap: wrap; }
.hero .actions { justify-content: center; }
.actions > * { margin: 0 !important; }

/* A picture of the product in a window with three dots, cut off at the bottom. */
.window-pic { margin: 48px auto 0; max-width: 1040px; background: var(--panel);
  border-radius: var(--pic-radius) var(--pic-radius) 0 0; padding: var(--min-gap) var(--min-gap) 0; text-align: left; }
.window-bar { display: flex; align-items: center; gap: 8px; padding: 4px 8px var(--min-gap); min-width: 0; }
.window-bar i { width: 12px; height: 12px; border-radius: 50%; background: var(--raised); flex: none; }
.window-bar .demo-name { margin-left: var(--min-gap); font-size: var(--text-small); color: var(--muted-fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.window-body { display: grid; grid-template-columns: 224px minmax(0, 1fr); gap: var(--gap);
  padding: var(--gap); background: var(--bg); border-radius: var(--card-radius) var(--card-radius) 0 0; }
.demo-side, .demo-stage { background: var(--panel); border-radius: var(--radius); --control: var(--bg); }
.demo-side { padding: 16px; display: flex; flex-direction: column; gap: var(--min-gap); }
.demo-side .say { font-weight: 600; margin: 0 0 4px; }
.demo-side .hint { margin: auto 0 0; }
.demo-side .chip { width: 100%; justify-content: flex-start; margin: 0; }
.chip[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
.demo-stage { min-height: var(--demo-height); padding: 16px; overflow-x: auto; }
.demo-view[hidden] { display: none; }
.demo-view { animation: rise .28s ease-out both; }
/* The spreadsheet: no gridlines, every second row a darker band. */
.sheet { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--text-small); font-variant-numeric: tabular-nums; }
.sheet th, .sheet td { padding: 8px 12px; text-align: left; white-space: nowrap; font-weight: 400; }
.sheet tr:nth-child(even) td { background: var(--bg); }
.sheet th { background: var(--raised); color: var(--muted-fg); font-weight: 600; }
.sheet td.cash { text-align: right; }
.sheet .tint { background: color-mix(in srgb, var(--hue) 26%, var(--panel)); }
.sheet tr:nth-child(even) .tint { background: color-mix(in srgb, var(--hue) 26%, var(--bg)); }
.sheet-tabs { display: flex; gap: 8px; margin-top: var(--min-gap); font-size: var(--text-small); color: var(--muted-fg); }
.sheet-tabs span { padding: 4px var(--min-gap); border-radius: 999px; background: var(--bg); }
.sheet-tabs span.on { color: var(--fg); background: var(--raised); }
.app-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--min-gap); margin-bottom: var(--min-gap); }
.app-head .h { font-size: var(--heading); font-weight: 600; }
.app-head span { color: var(--muted-fg); font-size: var(--text-small); }
.app-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); margin-bottom: var(--min-gap); }
.app-stats .box { display: flex; flex-direction: column; gap: 4px; }
.app-stats b { font-size: var(--figure); font-weight: 600; line-height: 1.1; }
.app-stats small { color: var(--muted-fg); font-size: var(--text-small); }
/* A share drawn as one bar split in two, with its sentence above it. */
.share-line { margin: 0 0 8px; color: var(--muted-fg); font-size: var(--text-small); }
.share { display: flex; gap: 4px; height: 16px; margin-bottom: var(--min-gap); }
.share i { display: block; height: 100%; border-radius: 8px; background: var(--hue); }
.share i.rest { background: var(--bg); }
.share .w17 { width: 17%; } .share .w83 { width: 83%; } .share .w33 { width: 33%; } .share .w67 { width: 67%; }
.app-rows { --cols: minmax(0, 1.2fr) minmax(0, 1.4fr) auto; }
.app-rows .row { padding: 8px var(--min-gap); }
.app-rows .when { color: var(--muted-fg); font-size: var(--text-small); }
.app-rows .badge { font-size: var(--text-small); padding: 4px var(--min-gap); }

/* Screenshots in a fixed shape, with their words underneath (no card).
   Pointing at one turns its name a shade of grey, like any link. */
.shots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px var(--min-gap); }
.shots.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.shots.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.shot { display: block; color: var(--fg); font-weight: 400; min-width: 0; }
.shot img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; object-position: top;
  border-radius: var(--pic-radius); background: var(--panel); }
a.shot:hover { color: var(--fg); }
a.shot:hover .cap b { color: var(--muted-fg); }
.shot .cap { display: block; margin-top: var(--min-gap); }
.shot .cap b { display: block; font-weight: 600; }
.shot .cap span { color: var(--muted-fg); }
.shot .cap .where { display: block; margin-top: 4px; font-size: var(--text-small); font-weight: 600; color: var(--fg); }

/* Twelve columns for cards side by side. */
.grid12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gap); }
.s2 { grid-column: span 2; } .s3 { grid-column: span 3; } .s4 { grid-column: span 4; }
.s5 { grid-column: span 5; } .s6 { grid-column: span 6; } .s7 { grid-column: span 7; }
.s8 { grid-column: span 8; } .s12 { grid-column: span 12; }
.cards2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
.cards3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); }
.cards4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap); }
.card > :last-child { margin-bottom: 0; }
.card.roomy { padding: 24px; }
.card.col { display: flex; flex-direction: column; }
.card.col > .btn { margin-top: auto; align-self: flex-start; }
.card.col > .facts-grid { flex: 1; grid-auto-rows: 1fr; }
.step > p, .tile > p { flex: 1; }
.card .card-title { margin-bottom: var(--min-gap); }
.card p { margin: 0 0 var(--min-gap); }
.muted-text, .card .muted-text { color: var(--muted-fg); }

/* A card that offers one thing, with its button at the bottom. One yellow spotlight card per page at most. */
.offer-card { display: flex; flex-direction: column; justify-content: space-between; gap: var(--min-gap); }
.offer-card .card-title, .offer-card p { margin: 0; }
.offer-card.lead-card .card-title { font-size: var(--display-3); font-weight: 600; letter-spacing: -.02em; line-height: 1.1; }
.offer-card .btn, .offer-card .btn-main { align-self: flex-start; margin-top: auto; }
.spot { background: var(--accent); color: var(--on-accent); --control: var(--bg); }
.spot .card-title, .spot a:not(.btn) { color: var(--on-accent); }
.spot p { color: var(--on-accent); }
.spot .btn { background: var(--bg); color: var(--fg); }
.spot .btn:hover { background: var(--raised); color: var(--fg); }

/* Lists: round markers, never ticks; round numbers for steps. */
.marks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.marks li { position: relative; padding-left: 24px; }
.marks li::before { content: ""; position: absolute; left: 4px; top: .6em; width: 8px; height: 8px; border-radius: 50%;
  background: var(--muted-fg); }
.n { flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  background: var(--raised); font-weight: 700; font-size: var(--text-small); }
.n.big { width: 44px; height: 44px; font-size: var(--heading); background: var(--control); }

/* Steps: numbered cards in a row. */
.steps-list { list-style: none; margin: 0; padding: 0; }
.step { display: flex; flex-direction: column; gap: var(--min-gap); }
.step h2, .step h3 { font-size: var(--heading); font-weight: 600; }
.step p { color: var(--muted-fg); margin: 0; }
.step .badge { align-self: flex-start; }

/* Rows of facts, each with a round grey icon. */
.info-row { display: flex; gap: 16px; align-items: flex-start; }
.info-row + .info-row { margin-top: 24px; }
.info-row .icon-circle { width: 44px; height: 44px; flex: none; }
.info-row .icon-circle svg { width: 20px; height: 20px; }
.info-row b { display: block; font-weight: 600; }
.info-row p { margin: 4px 0 0; color: var(--muted-fg); overflow-wrap: anywhere; }
.info-row > div { min-width: 0; }
.icon-circle svg, .iconbig svg, .icon-btn svg { fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round; }

/* Words beside a picture, side by side across the width. */
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 64px; align-items: center; }
.split.wide-pic { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.split h2 { margin-bottom: var(--min-gap); }
.split .band-lead { margin: 0 0 24px; }
.split .marks { margin-bottom: 24px; }
.split > div > .hint { margin-top: var(--min-gap); }
.frame { background: var(--panel); border-radius: var(--pic-radius); padding: 16px; }
.frame img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; object-position: top; border-radius: var(--card-radius); }

/* The part that is yours, on a base that is already written. Grey layers;
   only the layer you pay for takes a hue. */
.stack-pic { display: flex; flex-direction: column; gap: var(--gap); margin: 0; }
.stack-pic .yours { background: var(--hue); color: var(--on-accent); border-radius: var(--card-radius); padding: 24px; }
.stack-pic .yours b { display: block; font-size: var(--heading); }
.stack-pic .bricks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
.stack-pic .bricks span { border-radius: var(--card-radius); padding: 16px; font-weight: 600; background: var(--panel); }
.stack-pic figcaption { color: var(--muted-fg); font-size: var(--text-small); margin-top: 4px; }

/* Drawings: paint comes from the card's hue and the greys, never a colour of its own. */
.viz { display: block; font-family: var(--font); font-size: var(--text-legal); }
.viz text { fill: var(--muted-fg); font-weight: 500; }
.viz .t2 { fill: var(--fg); font-weight: 700; }
.viz .ink { fill: var(--on-accent); }
.viz .f { fill: var(--hue); }
.viz .f5 { fill: var(--hue); fill-opacity: .55; }
.viz .f2 { fill: var(--hue); fill-opacity: .25; }
.viz .s5 { fill: none; stroke: var(--hue); stroke-opacity: .5; stroke-width: 3; stroke-linecap: round; }
.viz .s { fill: none; stroke: var(--hue); stroke-width: 3; stroke-linecap: round; }
.viz .bg { fill: var(--bg); }
.viz .g { fill: var(--bg); }
.viz .card-bg { fill: var(--panel); }
.viz .box { fill: var(--raised); }
.viz .good { fill: var(--shade-green); font-weight: 600; }
.viz .bad { fill: var(--shade-red); font-weight: 600; }
.viz .glyph-l { fill: none; stroke: var(--fg); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.viz .glyph { fill: none; stroke: var(--on-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* The questions help centre: a search box first, five topic tiles with grey
   icons, then the most asked. No pictures. Every answer is shown in full. */
.help-head { text-align: center; }
.crumbs { margin-bottom: 16px; }
.help-search { max-width: 40rem; margin: 0 auto 32px; }
.help-search input[type="search"] { width: 100%; height: 48px; padding: 8px 24px; border-radius: 999px; }
.help-search label { padding-left: 24px; }
.help-search.left { margin-left: 0; }
.help-search.left .help-status { text-align: left; padding-left: 24px; }
.help-status { min-height: 24px; margin: 16px 0 0; text-align: center; color: var(--muted-fg); }
.help-status a { color: var(--fg); }
.help-h { font-size: var(--heading); font-weight: 600; margin: 48px 0 16px; }
.help-search + .help-results + [data-help-home] > .help-h:first-child { margin-top: 0; }
[hidden] { display: none !important; }
.topic-tiles { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--gap); }
.topic-tiles.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.topic-tiles.four.with-lead { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.topic-tile.lead { grid-column: span 2; }
.topic-tile { display: flex; flex-direction: column; gap: 4px; padding: 24px; min-width: 0;
  background: var(--panel); border-radius: var(--card-radius); color: var(--fg); --control: var(--bg); }
.topic-tile:hover { background: var(--raised); }
.topic-tile .iconbig { width: 56px; height: 56px; margin-bottom: 12px; }
.topic-tile .iconbig svg { width: 24px; height: 24px; }
.topic-tile .name { font-size: var(--heading); font-weight: 600; line-height: 1.25; }
.topic-tile .count { color: var(--muted-fg); font-size: var(--text-small); }
.most, .help-results { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); }
.qcard { display: flex; flex-direction: column; min-width: 0; padding: 24px; background: var(--panel);
  border-radius: var(--card-radius); --control: var(--bg); }
.qcard .tile-head { margin-bottom: 16px; }
.qcard .tile-head .icon-circle { width: 32px; height: 32px; flex: none; }
.qcard .tile-head .icon-circle svg { width: 16px; height: 16px; }
.qcard .topic-name { color: var(--muted-fg); font-size: var(--text-small); font-weight: 600; }
.qcard h3 { font-size: var(--card-heading); font-weight: 600; line-height: 1.3; margin: 0 0 var(--min-gap); }
.qcard h3 a, .qrow h2 a { color: var(--fg); }
.qcard .fact { font-size: var(--fact); font-weight: 600; line-height: 1.2; margin: 0 0 8px; }
.qcard .ans { margin: 0; color: var(--muted-fg); }
.qcard .ans a, .qrow p a { color: var(--fg); }
.qlist { background: var(--panel); border-radius: var(--card-radius); padding: 8px; }
.qrow { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: 32px; padding: 16px 24px;
  border-radius: var(--card-radius); }
.qrow:nth-child(even) { background: var(--bg); }
.qrow h2 { font-size: var(--card-heading); font-weight: 600; line-height: 1.3; margin: 0; }
.qrow b { display: block; font-size: var(--fact); font-weight: 600; line-height: 1.2; }
.qrow p { margin: 8px 0 0; color: var(--muted-fg); }
.qrow:target { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Fact tiles: the figure, its words, and a picture only where it shows something. */
.fact-tile { display: flex; align-items: center; gap: 16px; }
.fact-tile .viz { width: 64px; height: 64px; flex: none; }
.fact-tile .iconbig { width: 64px; height: 64px; }
.fact-col .iconbig { width: 56px; height: 56px; }
.fact-col .iconbig svg { width: 24px; height: 24px; }
.fact-tile b { display: block; font-size: var(--figure); font-weight: 600; line-height: 1.1; }
.fact-tile > span > span { display: block; color: var(--muted-fg); }
p.fact-tile { margin: 0; }
.fact-col { display: flex; flex-direction: column; justify-content: flex-start; gap: 16px; }
.facts-grid { gap: 24px var(--gap); }


/* The contact form. */
.enquiry { display: flex; flex-direction: column; }
.enquiry .form-row { margin-bottom: var(--min-gap); }
.enquiry .error-text { margin: 12px 0 0; min-height: 24px; }   /* the line is always there, so a problem appearing moves nothing */
.enquiry .field > .hint { margin: 8px 0 0; }
.enquiry .form-row > .name { flex: 0 1 16rem; }
.enquiry .field.grow { flex: 1; display: flex; flex-direction: column; }
.enquiry .field.grow textarea { flex: 1; }
.enquiry textarea { min-height: 144px; }
.enquiry .send { display: flex; align-items: center; gap: var(--min-gap) 24px; flex-wrap: wrap; margin-top: 16px; }
.enquiry .send .hint { margin: 0; flex: 1 1 16rem; }
.enquiry input.hp.visually-hidden { width: 1px; height: 1px; min-height: 0; padding: 0; border: 0; }   /* the trap for spam robots: 1px and out of sight */

/* Small cards with a big grey icon, a heading and a line. */
.tile { display: flex; flex-direction: column; gap: var(--min-gap); }
.tile h3 { font-size: var(--heading); font-weight: 600; }
.tile .iconbig { width: 56px; height: 56px; }
.tile .iconbig svg { width: 24px; height: 24px; }
.tile p { margin: 0; }
.duo { display: flex; flex-direction: column; gap: var(--min-gap); align-items: flex-start; }
.duo .card-title { margin-bottom: var(--min-gap); }
.co-big { font-size: var(--heading); font-weight: 600; line-height: 1.25; margin: 0 0 8px; overflow-wrap: anywhere; }

/* The closing card: one call to action beside what happens next. */
.closing { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 48px;
  align-items: center; text-align: left; padding: 48px; margin-top: var(--section-gap); }
.closing h2 { font-size: var(--display-3); font-weight: 500; letter-spacing: -.02em; margin: 0 0 var(--min-gap); }
.closing .line { color: var(--muted-fg); font-size: var(--lead); margin: 0 0 24px; }
.next-box { background: var(--bg); border-radius: var(--pic-radius); padding: 24px; --control: var(--panel); }
.next-box h3 { font-size: var(--card-heading); font-weight: 600; margin: 0 0 var(--min-gap); }
.next-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 16px; }
.next-list li { display: flex; align-items: center; gap: 16px; }

/* Legal pages: every word shown, as one card across the full width with the
   text in two balanced columns (the approved article layout). */
.legal-cols { columns: 2; column-gap: 64px; background: var(--panel); border-radius: var(--card-radius); padding: 32px; }
.legal-cols > section { margin: 0 0 24px; }
.legal-cols > section:last-child { margin-bottom: 0; }
.legal-cols h2 { font-size: var(--heading); font-weight: 600; margin-bottom: var(--min-gap); break-after: avoid; }
.legal-cols p, .legal-cols li { orphans: 1; widows: 1; }
.legal-cols .marks { margin-bottom: var(--min-gap); }
.legal-cols > section > :last-child { margin-bottom: 0; }

/* Narrower windows: the same order, fewer columns. */
@media (max-width: 1000px) {
  .shots.four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .closing { grid-template-columns: 1fr; padding: 32px; }
  .split, .split.wide-pic { grid-template-columns: 1fr; gap: 32px; }
}
@media (max-width: 860px) { .cards4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px) {
  :root { --section-gap: 64px; }
  .window-body { grid-template-columns: 1fr; }
  .demo-side .hint { margin-top: 4px; }
  .shots, .shots.two, .cards2 { grid-template-columns: 1fr; }
  .cards3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .topic-tiles, .topic-tiles.four, .topic-tiles.four.with-lead, .most, .help-results { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid12 > * { grid-column: 1 / -1 !important; }
  .app-rows { --cols: minmax(0, 1fr) auto; }
  .app-rows .when { display: none; }
  .legal-cols { columns: 1; padding: 24px; }
}
@media (max-width: 640px) {
  .qrow { grid-template-columns: 1fr; gap: 8px; padding: 16px; }
}
@media (max-width: 520px) {
  .topic-tiles, .topic-tiles.four, .topic-tiles.four.with-lead, .most, .help-results { grid-template-columns: 1fr; }
  .topic-tile.lead { grid-column: auto; }
  .shots.four, .cards4, .cards3 { grid-template-columns: 1fr; }
  .closing { padding: 24px; }
  .app-stats { grid-template-columns: 1fr 1fr; }
  .app-stats .box:last-child { display: none; }
  .footer-legal { grid-template-columns: 1fr; }
  .footer-legal .extra, .footer-legal .legal { grid-column: 1; justify-content: flex-start; }
  .actions { flex-direction: column; align-items: stretch; }
  .actions > * { justify-content: center; }
}

/* The page-not-found page: the headline, then a spreadsheet with one broken cell. */
.lost-code { margin: 0 0 var(--min-gap); font-size: var(--text-small); color: var(--muted-fg); font-variant-numeric: tabular-nums; }
.lost .lost-pic { margin-top: 48px; max-width: 720px; }
.lost-ref { color: var(--danger); font-weight: 600; }

/* The apps grid stays hidden while the live list is on its way (apps.js). */
.apps-wait #apps-grid { visibility: hidden; }

/* A highlighted app fills a square of four cards (2 wide, 2 tall). */
.shot.featured { grid-column: span 2; grid-row: span 2; display: flex; flex-direction: column; }
.shot.featured img { flex: 1 1 auto; min-height: 0; height: 100%; aspect-ratio: auto; object-position: left top; }
.shot.featured .cap b { font-size: var(--heading); }
@media (max-width: 1000px) { .shots.four .shot.featured { grid-row: span 1; } .shots.four .shot.featured img { aspect-ratio: 16 / 9; height: auto; flex: 0 0 auto; } }
@media (max-width: 760px) { .shots .shot.featured { grid-column: span 1; grid-row: span 1; } .shots .shot.featured img { aspect-ratio: 16 / 9; height: auto; flex: 0 0 auto; } }
