/* ==========================================================================
   Turtle Labs components.

   One definition per thing, used by all seven sites. A surface supplies
   colour and nothing else.

   This exists because the same handful of components had been written eight
   and nine times over. A text input was styled independently as `form input`,
   `.referform input`, `.sheet-form input`, `.audit-form input`, `.reaudit
   input`, `.field input`, `.signin-form input` and `.inline-form input`; the
   selectable choice card as `.pf-opt`, `.q-scale`, `.q-opts` and `.g-opt`.
   Every correction then had to be made eight times, and the ones that were
   missed are what a design review keeps finding.

   The rule for adding to this file: a component goes here the second time it
   is needed. The rule for using it: a site may set tokens, and may not
   redefine padding, radius, border or type. checks/components.js enforces
   the second half.

   Tokens a surface is expected to provide, all with fallbacks here so a
   component still renders if one is missing:

     --bg --bg2 --surface --text --muted --faint --line --line2
     --cta --cta-ink --cta-text --accent-soft
     --r-sm --r-md --r-lg --r-pill

   The accent is the one that bites. Three surfaces name it --cta, three name
   it --accent, and tl-system named it --green and nothing else, so every
   filled component on the group, Useful Store and BrandOS surfaces resolved
   its ink to the literal #fff and rendered white text on a white card in the
   light theme. Each surface now declares --cta and --cta-ink, and the
   fallbacks below chain through all three names so a new surface that forgets
   is merely wrong rather than invisible. checks/tokens.js asserts the
   declaration.

   ========================================================================== */

/* ---- rhythm --------------------------------------------------------------
   Two primitives instead of a margin on every element. Stacks own the space
   between their children, so a component dropped into one is spaced without
   knowing where it is.
   ------------------------------------------------------------------------ */
.tl-stack        { display: flex; flex-direction: column; gap: var(--tl-gap, 18px); }
.tl-stack-sm     { --tl-gap: 10px; }
.tl-stack-lg     { --tl-gap: 28px; }
.tl-row          { display: flex; flex-wrap: wrap; gap: var(--tl-gap, 14px); align-items: center; }
.tl-row-tight    { --tl-gap: 8px; }

/* ---- section heading -----------------------------------------------------
   Eyebrow, heading, lede. Written out per section across four sites, with the
   gaps between the three parts different every time.
   ------------------------------------------------------------------------ */
.tl-head { display: flex; flex-direction: column; gap: 12px; margin-bottom: 32px; }
.tl-head .tl-eyebrow { margin: 0; }
.tl-head h2, .tl-head h3 { margin: 0; }
.tl-head p { margin: 0; color: var(--muted); font-size: clamp(15.5px, 1.6vw, 18px);
             line-height: 1.6; max-width: 62ch; }
.tl-head.is-centred { align-items: center; text-align: center; }
.tl-head.is-centred p { margin-inline: auto; }

.tl-eyebrow { font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
              font-weight: 800; color: var(--cta-text, var(--cta, var(--accent, var(--muted))));
              display: inline-flex; align-items: center; gap: 10px; }
.tl-eyebrow::before { content: ''; width: 22px; height: 2px; border-radius: 2px;
                      background: currentColor; flex: none; }

/* ---- surfaces ------------------------------------------------------------
   One card. Variants change colour and weight, never the geometry, which is
   why a corner or a padding can be corrected in one place.
   ------------------------------------------------------------------------ */
.tl-card {
  background: var(--surface, var(--bg2));
  border: 1px solid var(--line2, var(--line));
  border-radius: var(--r-lg, 18px);
  padding: clamp(20px, 2.2vw, 30px);
  display: flex; flex-direction: column; gap: 14px;
}
.tl-card.is-quiet   { background: transparent; }
.tl-card.is-raised  { background: var(--bg2, var(--surface)); }
.tl-card.is-accent  { border-color: var(--cta, var(--accent, var(--green))); }
/* The one a reader is meant to take: filled, not outlined. */
.tl-card.is-chosen  { background: var(--cta, var(--accent, var(--green))); border-color: var(--cta, var(--accent, var(--green)));
                      color: var(--cta-ink, var(--accent-ink, var(--green-ink, #fff))); position: relative; }
.tl-card.is-chosen :is(p, li, span):not(.tl-badge) { color: inherit; opacity: .82; }
.tl-card.is-chosen :is(h2, h3, h4, strong) { color: inherit; opacity: 1; }
.tl-card > :is(h2, h3, h4) { margin: 0; }
.tl-card > p:not([class]) { margin: 0; color: var(--muted); line-height: 1.6; }
.tl-card > p { margin: 0; line-height: 1.6; }

/* Equal-width card grids, one definition. */
.tl-cards { display: grid; gap: clamp(12px, 1.4vw, 20px);
            grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--tl-col, 260px)), 1fr)); }
.tl-cards.is-wide   { --tl-col: 320px; }
.tl-cards.is-narrow { --tl-col: 200px; }

/* ---- badge ---------------------------------------------------------------
   The pill. Takes its colour from --tone, so one rule covers a status, a
   category and a price label.
   ------------------------------------------------------------------------ */
.tl-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: var(--r-pill, 999px);
  font-size: 11.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  background: color-mix(in srgb, var(--tone, var(--cta, #888)) 14%, transparent);
  color: var(--tone-ink, var(--tone, var(--cta, var(--accent, var(--green)))));
  border: 1px solid color-mix(in srgb, var(--tone, var(--cta, #888)) 34%, transparent);
  white-space: nowrap;
}
.tl-badge.is-solid { background: var(--tone, var(--cta, var(--accent, var(--green)))); color: var(--cta-ink, var(--accent-ink, var(--green-ink, #fff)));
                     border-color: transparent; }
/* Sitting on the lip of a card, which is where "most chosen" goes. */
.tl-badge.is-pinned { position: absolute; top: -11px; left: 22px; }
.tl-card:has(> .tl-badge.is-pinned) { padding-top: clamp(26px, 2.6vw, 34px); }
@supports not selector(:has(*)) {
  .tl-card > .tl-badge.is-pinned + * { margin-top: 8px; }
}
/* A badge pinned to a filled card takes the card's ink, not the spectrum hue
   its position happens to give it: a crimson tag on a green card reads as a
   warning rather than as a recommendation. */
.tl-card.is-chosen > .tl-badge.is-solid {
  background: var(--cta-ink, var(--accent-ink, #fff));
  color: var(--cta, var(--accent, var(--green)));
}

/* And a button on one. The secondary weight is accent-tinted, which is
   accent-on-accent once the card is filled with the accent: measured at 1:1,
   which is not low contrast, it is no contrast. On a filled card the button
   inverts, the way the plan cards already do it by hand. */
.tl-card.is-chosen .btn,
.tl-card.is-chosen .btn.primary {
  background: var(--cta-ink, var(--accent-ink, #fff));
  border-color: var(--cta-ink, var(--accent-ink, #fff));
  color: var(--cta, var(--accent, var(--green)));
}
@media (hover: hover) {
  .tl-card.is-chosen .btn:hover,
  .tl-card.is-chosen .btn.primary:hover {
    filter: brightness(1.08);
    background: var(--cta-ink, var(--accent-ink, #fff));
    color: var(--cta, var(--accent, var(--green)));
  }
}

/* ---- form ----------------------------------------------------------------
   A field is a label and a control. The label is always present and always
   above: a placeholder is not a label, it disappears the moment somebody
   starts typing, and that is when they most need to know what the box is.
   ------------------------------------------------------------------------ */
.tl-form { display: flex; flex-direction: column; gap: 16px; }
/* Two fields to a row on anything wider than a phone: a six-field form in one
   column reads as a much longer form than it is. */
.tl-form-grid { display: grid; gap: 14px 16px; grid-template-columns: 1fr; }
@media (min-width: 620px) { .tl-form-grid { grid-template-columns: 1fr 1fr; } }
.tl-form-grid .tl-field.is-full { grid-column: 1 / -1; }

.tl-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.tl-field > label, .tl-label {
  font-size: 12.5px; font-weight: 700; color: var(--text);
  display: flex; align-items: baseline; gap: 7px;
}
.tl-label .tl-opt { font-weight: 400; color: var(--faint); font-size: 11.5px; }

.tl-field :is(input[type=text], input[type=email], input[type=tel], input[type=url],
              input[type=number], input[type=date], input:not([type]), textarea, select),
.tl-input {
  width: 100%; min-width: 0; box-sizing: border-box;
  padding: 11px 14px; font: inherit; font-size: 15px; line-height: 1.4;
  color: var(--text); background: var(--bg, transparent);
  border: 1px solid var(--line, rgba(128,128,128,.3));
  border-radius: var(--r-sm, 10px);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.tl-field textarea { resize: vertical; min-height: 92px; }
.tl-field select { appearance: none; -webkit-appearance: none; padding-right: 38px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 19px) calc(50% + 2px), calc(100% - 14px) calc(50% + 2px);
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
.tl-field :is(input, textarea, select):focus-visible {
  outline: none; border-color: var(--cta, var(--accent, var(--green)));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cta, var(--accent, var(--green))) 22%, transparent);
}
.tl-field :is(input, textarea, select)[aria-invalid="true"] { border-color: #E4553F; }
.tl-field .tl-note { font-size: 12px; color: var(--faint); }
.tl-field .tl-note.is-error { color: #E4553F; }

/* A checkbox with its sentence, which is always a consent line here. */
.tl-check { display: flex; gap: 10px; align-items: flex-start;
            font-size: 13px; line-height: 1.55; color: var(--muted); }
.tl-check input { margin: 2px 0 0; flex: none; accent-color: var(--cta, var(--accent, var(--green))); }

/* ---- button --------------------------------------------------------------
   The second full copy of a component, found by the gallery rather than by
   reading: tl-system.css and webos.css each defined the whole .btn family,
   with different padding (28px against 20px) and opposite secondary styling,
   and the tracker loaded neither, so its buttons were the browser's.

   The secondary weight is accent-tinted rather than a hairline outline. Most
   buttons on these sites are the secondary one, and as a transparent pill it
   read as a disabled control next to body text.
   ------------------------------------------------------------------------ */
.btn, .tl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px clamp(20px, 2vw, 28px);
  font-family: inherit; font-weight: 700; font-size: 15px; line-height: 1.2;
  text-decoration: none; cursor: pointer; border-radius: var(--r-pill, 999px);
  border: 1px solid var(--cta, var(--accent, var(--green)));
  color: var(--cta-text, var(--cta, var(--accent, var(--green))));
  background: var(--accent-soft, color-mix(in srgb, var(--cta, var(--accent, var(--green))) 10%, transparent));
  transition: transform .3s cubic-bezier(.22,.61,.36,1), background-color .25s ease,
              border-color .25s ease, color .25s ease, box-shadow .3s ease;
}
@media (hover: hover) {
  .btn:hover, .tl-btn:hover {
    background: var(--cta, var(--accent, var(--green)));
    color: var(--cta-ink, var(--accent-ink, var(--green-ink, #fff)));
    border-color: var(--cta, var(--accent, var(--green)));
    transform: translateY(-2px);
  }
}
.btn.primary, .tl-btn.primary {
  background: var(--cta, var(--accent, var(--green)));
  border-color: var(--cta, var(--accent, var(--green)));
  color: var(--cta-ink, var(--accent-ink, var(--green-ink, #fff)));
}
@media (hover: hover) {
  .btn.primary:hover, .tl-btn.primary:hover {
    filter: brightness(1.08); transform: translateY(-2px);
    color: var(--cta-ink, var(--accent-ink, var(--green-ink, #fff)));
    box-shadow: 0 10px 24px rgba(0,0,0,.18);
  }
}
/* A third weight, for the times a button genuinely should recede: a back
   link, a cancel. Opt in by name rather than by being the default.
   `.ghost` is the name the CRM and Find Your Passion had already given it. */
.btn.quiet, .btn.ghost, .tl-btn.quiet {
  background: transparent; border-color: var(--line); color: var(--text);
}
@media (hover: hover) {
  .btn.quiet:hover, .btn.ghost:hover, .tl-btn.quiet:hover {
    background: var(--bg2, var(--surface)); border-color: var(--text); color: var(--text);
  }
}
.btn:disabled, .tl-btn:disabled { opacity: .45; cursor: default; transform: none; }
.btn.wide, .tl-btn.wide { width: 100%; }
.btn:focus-visible, .tl-btn:focus-visible {
  outline: 2px solid var(--cta, var(--accent, var(--green))); outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .btn, .btn:hover, .btn.primary:hover, .tl-btn, .tl-btn:hover { transform: none; }
}

/* ---- choice --------------------------------------------------------------
   The selectable card: a radio drawn as a target big enough to hit. Written
   four times over as .pf-opt, .q-scale, .q-opts and .g-opt, each with its own
   hit area and its own idea of what "selected" looks like.
   ------------------------------------------------------------------------ */
.tl-choices { display: grid; gap: 10px;
              grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); }
.tl-choices.is-stacked { grid-template-columns: 1fr; }

.tl-choice {
  position: relative; display: flex; flex-direction: column; gap: 3px;
  padding: 15px 44px 15px 17px; cursor: pointer;
  background: var(--surface, var(--bg2)); color: var(--text);
  border: 1px solid var(--line, rgba(128,128,128,.3));
  border-radius: var(--r-md, 14px);
  transition: border-color .18s ease, background-color .18s ease, transform .18s ease;
}
.tl-choice input { position: absolute; opacity: 0; width: 0; height: 0; }
.tl-choice .tl-choice-t { font-weight: 700; font-size: 15px; }
.tl-choice .tl-choice-d { font-size: 13px; color: var(--muted); line-height: 1.5; }
/* The ring, always drawn, so the control reads as choosable before it is hot. */
.tl-choice::after {
  content: ''; position: absolute; top: 50%; right: 16px; transform: translateY(-50%);
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--line, rgba(128,128,128,.4));
  transition: border-color .18s ease, box-shadow .18s ease;
}
@media (hover: hover) {
  .tl-choice:hover { border-color: var(--cta, var(--accent, var(--green))); transform: translateY(-1px); }
  .tl-choice:hover::after { border-color: var(--cta, var(--accent, var(--green))); }
}
.tl-choice:has(input:checked) {
  border-color: var(--cta, var(--accent, var(--green)));
  background: var(--accent-soft, color-mix(in srgb, var(--cta, #888) 10%, transparent));
}
.tl-choice:has(input:checked)::after {
  border-color: var(--cta, var(--accent, var(--green)));
  box-shadow: inset 0 0 0 4px var(--cta, var(--accent, var(--green)));
}
.tl-choice:has(input:focus-visible) { outline: 2px solid var(--cta, var(--accent, var(--green))); outline-offset: 2px; }
/* Without :has, the selected state still has to be visible. */
@supports not selector(:has(*)) {
  .tl-choice input:checked ~ .tl-choice-t { text-decoration: underline; }
}
@media (prefers-reduced-motion: reduce) { .tl-choice, .tl-choice:hover { transform: none; } }

/* ---- progress ------------------------------------------------------------
   A stepped form that does not say how long it is asks somebody to commit to
   an unknown number of questions.
   ------------------------------------------------------------------------ */
.tl-progress { display: flex; flex-direction: column; gap: 8px; }
.tl-progress-bar { height: 5px; border-radius: var(--r-pill, 999px);
                   background: var(--line2, rgba(128,128,128,.18)); overflow: hidden; }
.tl-progress-bar > span { display: block; height: 100%; border-radius: inherit;
                          background: var(--cta, var(--accent, var(--green)));
                          transition: width .35s cubic-bezier(.22,.61,.36,1); }
.tl-progress-text { font-size: 12px; font-weight: 700; color: var(--faint);
                    letter-spacing: .04em; }

/* ---- figures -------------------------------------------------------------
   Numbers presented as numbers. A result read as a sentence is a result
   nobody remembers.
   ------------------------------------------------------------------------ */
.tl-figures { display: grid; gap: clamp(12px, 1.4vw, 18px);
              grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); }
.tl-figure { display: flex; flex-direction: column; gap: 4px;
             padding: clamp(16px, 1.8vw, 22px);
             background: var(--surface, var(--bg2));
             border: 1px solid var(--line2, var(--line));
             border-radius: var(--r-md, 14px);
             border-top: 3px solid var(--tone, var(--cta, var(--accent, var(--green)))); }
.tl-figure-n { font-family: 'Outfit', system-ui, sans-serif; font-weight: 900;
               font-size: clamp(26px, 3vw, 36px); line-height: 1;
               color: var(--tone-ink, var(--tone, var(--cta, var(--accent, var(--green))))); letter-spacing: -.02em; }
.tl-figure-l { font-size: 13.5px; font-weight: 700; color: var(--text); }
.tl-figure-s { font-size: 12.5px; color: var(--faint); line-height: 1.5; }

/* ---- disclosure ----------------------------------------------------------
   Used by the Commons and wanted in several other places, so it lives here.
   ------------------------------------------------------------------------ */
.tl-fold { border-top: 1px solid var(--line2, var(--line)); }
.tl-fold:last-of-type { border-bottom: 1px solid var(--line2, var(--line)); }
.tl-fold > summary { cursor: pointer; padding: 15px 2px; font-weight: 700; font-size: 15.5px;
                     list-style: none; display: flex; align-items: center; gap: 10px; }
.tl-fold > summary::-webkit-details-marker { display: none; }
.tl-fold > summary::before { content: '+'; width: 18px; flex: none; font-weight: 400;
                             font-size: 18px; color: var(--muted); }
.tl-fold[open] > summary::before { content: '\2212'; }
.tl-fold > summary:hover { color: var(--cta-text, var(--cta)); }
.tl-fold-body { padding: 0 2px 20px 28px; }
.tl-fold-body > * { margin-top: 0; }
@media (max-width: 620px) { .tl-fold-body { padding-left: 4px; } }

/* ---- side note -----------------------------------------------------------
   Guidance that belongs beside the thing it is about rather than under it.
   ------------------------------------------------------------------------ */
.tl-aside { display: grid; gap: clamp(18px, 2.4vw, 34px); align-items: start;
            grid-template-columns: 1fr; }
@media (min-width: 900px) { .tl-aside { grid-template-columns: 1.35fr .85fr; } }
.tl-aside-note { display: flex; flex-direction: column; gap: 12px;
                 padding: clamp(18px, 2vw, 24px);
                 background: var(--bg2, var(--surface));
                 border: 1px solid var(--line2, var(--line));
                 border-radius: var(--r-md, 14px); }
.tl-aside-note h3 { margin: 0; font-size: 15px; }
.tl-aside-note ul { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 9px; }
.tl-aside-note li { font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.tl-aside-note li::marker { color: var(--cta, var(--accent, var(--green))); }

/* ---- names the components answer to --------------------------------------
   Four surfaces had already invented a field: `.field` on BrandOS and Shell,
   `.referform` and `.sheet-form` on Find Your Passion. Rather than rewrite
   every form's markup in one go, those names point at the component here and
   their local rules are deleted, so there is one definition either way.

   This list is expected to shrink. A form moves to .tl-field markup when it
   is next touched, and its name comes out of here.
   ------------------------------------------------------------------------ */
.field, .referform label, .sheet-form label, .day-form label {
  display: flex; flex-direction: column; gap: 6px; min-width: 0; margin: 0;
}
.field > span, .referform label > span, .sheet-form label > span {
  font-size: 12.5px; font-weight: 700; color: var(--text);
}
.field :is(input, textarea, select),
.referform :is(input, textarea, select),
.sheet-form :is(input, textarea, select),
.day-form :is(input, textarea) {
  width: 100%; min-width: 0; box-sizing: border-box;
  padding: 11px 14px; font: inherit; font-size: 15px; line-height: 1.4;
  color: var(--text); background: var(--bg, transparent);
  border: 1px solid var(--line, rgba(128,128,128,.3));
  border-radius: var(--r-sm, 10px);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.field textarea, .referform textarea, .sheet-form textarea, .day-form textarea {
  resize: vertical; min-height: 92px;
}
.field :is(input, textarea, select):focus-visible,
.referform :is(input, textarea, select):focus-visible,
.sheet-form :is(input, textarea, select):focus-visible,
.day-form :is(input, textarea):focus-visible {
  outline: none; border-color: var(--cta, var(--accent, var(--green)));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cta, var(--accent, var(--green))) 22%, transparent);
}
.referform, .sheet-form { display: flex; flex-direction: column; gap: 16px; }
.referform .row { display: grid; gap: 14px 16px; grid-template-columns: 1fr; }
@media (min-width: 620px) { .referform .row { grid-template-columns: 1fr 1fr; } }

/* ==========================================================================
   Infographic components.

   Every design review so far has produced the same sentence about a different
   page: text-heavy, plain, dull, needs icons, needs colour, make it an
   infographic. That kept recurring because each page was composed by hand, so
   richness depended on whoever wrote it remembering to add it.

   These are the pieces that sentence is asking for. lib/page-kit.js renders
   them from data, so a section built through the kit cannot come out plain:
   it has a slot for the number, the icon and the hue whether or not anyone
   thought about them.
   ========================================================================== */

/* ---- the spectrum ---------------------------------------------------------
   Hand a list of anything this class and its children take the brand spectrum
   in order, looping after nine. Every component below reads --tone, so one
   class colours a whole section without a per-item decision.

   The ink tones, not the display tones: these land on text and on small
   marks, which WCAG asks 4.5:1 of. No literal fallbacks, deliberately: the
   first version of this carried the dark-theme values as fallbacks, and on a
   surface that had not declared the palette every one of them was used on a
   light page at 3.4:1. A missing token should be visibly missing, not quietly
   wrong. tl-system.css and webos.css both declare the set, per theme, which
   between them covers every surface.
   ------------------------------------------------------------------------ */
.tl-spectrum > *:nth-child(9n+1) { --tone: var(--tl-crimson-ink); }
.tl-spectrum > *:nth-child(9n+2) { --tone: var(--tl-red-ink); }
.tl-spectrum > *:nth-child(9n+3) { --tone: var(--tl-amber-ink); }
.tl-spectrum > *:nth-child(9n+4) { --tone: var(--tl-green-ink); }
.tl-spectrum > *:nth-child(9n+5) { --tone: var(--tl-teal-ink); }
.tl-spectrum > *:nth-child(9n+6) { --tone: var(--tl-cyan-ink); }
.tl-spectrum > *:nth-child(9n+7) { --tone: var(--tl-blue-ink); }
.tl-spectrum > *:nth-child(9n+8) { --tone: var(--tl-indigo-ink); }
.tl-spectrum > *:nth-child(9n+9) { --tone: var(--tl-violet-ink); }

/* ---- edged card -----------------------------------------------------------
   A card with its hue down the leading edge. Asked for by name: "gradient
   borders on left of the container". The edge is a gradient from the hue to
   transparent rather than a flat rule, so a column of them reads as a set
   rather than as a row of tabs.
   ------------------------------------------------------------------------ */
.tl-card.is-edged { position: relative; overflow: hidden; padding-left: clamp(20px, 2.2vw, 30px); }
.tl-card.is-edged::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: 4px;
  background: linear-gradient(180deg,
    var(--tone, var(--cta, var(--accent))) 0%,
    color-mix(in srgb, var(--tone, var(--cta, var(--accent))) 30%, transparent) 100%);
}
/* Topped instead, for a grid where a left edge would read as a margin. */
.tl-card.is-topped { position: relative; overflow: hidden; }
.tl-card.is-topped::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg,
    var(--tone, var(--cta, var(--accent))) 0%,
    color-mix(in srgb, var(--tone, var(--cta, var(--accent))) 25%, transparent) 100%);
}

/* ---- icon chip ------------------------------------------------------------
   A square plate carrying an emoji, an SVG or two letters, tinted with the
   item's hue. Text-based on purpose: an icon font is another network request
   and another thing to go wrong, and two letters read at any size.
   ------------------------------------------------------------------------ */
.tl-icon {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 38px; height: 38px; border-radius: var(--r-sm, 10px);
  font-size: 17px; line-height: 1; font-weight: 800; letter-spacing: .01em;
  background: color-mix(in srgb, var(--tone, var(--cta, var(--accent))) 15%, transparent);
  color: var(--tone, var(--cta, var(--accent)));
}
.tl-icon.is-sm { width: 30px; height: 30px; font-size: 13.5px; border-radius: var(--r-xs, 8px); }
.tl-icon.is-lg { width: 48px; height: 48px; font-size: 22px; border-radius: var(--r-md, 14px); }
.tl-icon.is-solid { background: var(--tone, var(--cta, var(--accent)));
                    color: var(--cta-ink, var(--accent-ink, var(--green-ink, #fff))); }
.tl-icon.is-round { border-radius: var(--r-pill, 999px); }
/* An emoji must not be recoloured, and must not inherit the plate's weight. */
.tl-icon .emo { font-weight: 400; font-style: normal;
                font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif; }

/* ---- steps ----------------------------------------------------------------
   A numbered sequence: the six fortnights, the five days, the path. The
   number is the ornament, in the item's hue, and the rule between items is
   what makes it read as an order rather than as a list of cards.
   ------------------------------------------------------------------------ */
.tl-steps { display: grid; gap: clamp(12px, 1.4vw, 18px);
            grid-template-columns: repeat(auto-fit, minmax(var(--tl-col, 250px), 1fr)); }
.tl-steps.is-stacked { grid-template-columns: 1fr; gap: 0; }
.tl-step { position: relative; display: flex; flex-direction: column; gap: 8px;
           padding: clamp(18px, 2vw, 24px);
           background: var(--surface, var(--bg2)); border: 1px solid var(--line);
           border-radius: var(--r-md, 14px); }
.tl-steps.is-stacked .tl-step { background: transparent; border: 0;
  border-top: 1px solid var(--line); border-radius: 0;
  display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; align-items: start; }
.tl-steps.is-stacked .tl-step:last-child { border-bottom: 1px solid var(--line); }
.tl-step-n { font-family: 'Outfit', system-ui, sans-serif; font-weight: 900;
             font-size: clamp(22px, 2.4vw, 30px); line-height: 1;
             color: var(--tone, var(--cta, var(--accent))); }
.tl-steps.is-stacked .tl-step-n { grid-row: 1 / span 3; font-size: clamp(24px, 3vw, 36px); }
.tl-step-when { font-size: 11.5px; font-weight: 800; letter-spacing: .1em;
                text-transform: uppercase; color: var(--faint); }
.tl-step h3, .tl-step h4 { margin: 0; font-size: 16px; }
.tl-step p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--muted); }
.tl-step .tl-step-out { font-size: 13.5px; line-height: 1.55; color: var(--muted);
                        padding-top: 8px; border-top: 1px dashed var(--line2, var(--line)); }
.tl-step .tl-step-out strong { color: var(--tone, var(--text)); }

/* ---- who / what / why -----------------------------------------------------
   Three short answers instead of three paragraphs. The heading is the
   question, so the copy underneath does not have to restate it.
   ------------------------------------------------------------------------ */
.tl-qa { display: grid; gap: clamp(12px, 1.6vw, 22px);
         grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.tl-qa-item { display: flex; flex-direction: column; gap: 9px; }
.tl-qa-item > h3 { margin: 0; font-size: 13px; letter-spacing: .1em;
                   text-transform: uppercase; color: var(--tone, var(--cta-text, var(--cta))); }
.tl-qa-item > p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--text); }

/* ---- highlights -----------------------------------------------------------
   The band directly under a hero: what this is, in four or five marks, before
   anyone has to read a paragraph.
   ------------------------------------------------------------------------ */
.tl-highlights { display: grid; gap: clamp(10px, 1.2vw, 16px);
                 grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.tl-highlight { display: flex; gap: 13px; align-items: flex-start;
                padding: clamp(14px, 1.5vw, 18px);
                border: 1px solid var(--line); border-radius: var(--r-md, 14px);
                background: color-mix(in srgb, var(--tone, var(--cta)) 6%, transparent); }
.tl-highlight-b { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.tl-highlight-t { font-size: 14.5px; font-weight: 700; line-height: 1.35; }
.tl-highlight-d { font-size: 13px; line-height: 1.5; color: var(--muted); }

/* ---- inclusions -----------------------------------------------------------
   What a package contains, as rows rather than prose. Three columns: the
   mark, what it is, and the one word for what it does.
   ------------------------------------------------------------------------ */
.tl-includes { list-style: none; margin: 0; padding: 0;
               display: flex; flex-direction: column; }
.tl-include { display: grid; grid-template-columns: auto 1fr auto;
              align-items: center; gap: 12px; padding: 10px 0;
              border-bottom: 1px solid var(--line2, var(--line)); }
.tl-include:last-child { border-bottom: 0; }
.tl-include-n { font-size: 14.5px; font-weight: 700; min-width: 0; }
.tl-include-d { font-size: 12.5px; color: var(--muted); display: block; font-weight: 400; }
.tl-include-v { font-size: 11px; font-weight: 800; letter-spacing: .09em;
                text-transform: uppercase; color: var(--tone, var(--faint)); white-space: nowrap; }
.tl-includes { container-type: inline-size; }
@container (max-width: 330px) {
  .tl-include { grid-template-columns: auto 1fr; }
  .tl-include-v { grid-column: 2; }
}
@supports not (container-type: inline-size) {
  @media (max-width: 560px) {
    .tl-include { grid-template-columns: auto 1fr; }
    .tl-include-v { grid-column: 2; }
  }
}

/* A choice used as a scale point: five across a row, so the label is the
   whole target and the row reads as a scale rather than as five cards. */
.tl-choice.is-compact { padding: 13px 14px; text-align: center; align-items: center; }
.tl-choice.is-compact::after { display: none; }
.tl-choice.is-compact .tl-choice-t { font-size: 13.5px; font-weight: 600; }
.tl-choice.is-compact:has(input:checked) .tl-choice-t { font-weight: 800; }
.tl-choices.is-scale { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }

/* ---- phone ----------------------------------------------------------------
   A country code and a number, drawn as one control.

   The two sit in a single bordered box with the rule between them, because
   they are one answer: a select beside an input, each with its own border,
   reads as two unrelated questions.

   The code is a real <select> rather than a scripted combo box. It works with
   scripting off, it is type-ahead searchable on every platform, and it is the
   control a phone already knows how to present full screen.

   Every rule below carries the .tl-field prefix as well. The field reset
   further up is `.tl-field :is(input[type=text], ..., select)`, which is
   (0,2,1): a plain `.tl-phone > select` is (0,1,1) and loses to it whatever
   the source order, which is how the first version of this lost its divider
   and its chevron and rendered as one flat box.
   ------------------------------------------------------------------------ */
.tl-phone {
  display: grid; grid-template-columns: 7.4rem minmax(0, 1fr);
  align-items: stretch; min-width: 0;
  border: 1px solid var(--line, rgba(128,128,128,.3));
  border-radius: var(--r-sm, 10px);
  background: var(--bg, transparent);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.tl-phone:focus-within {
  border-color: var(--cta, var(--accent, var(--green)));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cta, var(--accent, var(--green))) 22%, transparent);
}

.tl-field .tl-phone > select, .tl-phone > select {
  width: 100%; min-width: 0; text-overflow: ellipsis;
  margin: 0; padding: 11px 26px 11px 13px;
  font: inherit; font-size: 14px; line-height: 1.4;
  color: var(--text); cursor: pointer;
  background-color: transparent;
  border: 0; border-right: 1px solid var(--line, rgba(128,128,128,.3));
  border-radius: 0; box-shadow: none; outline: none;
  appearance: none; -webkit-appearance: none;
  /* A drawn chevron rather than gradient triangles: at 5px those were
     invisible on both themes. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23888' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-position: calc(100% - 9px) 50%;
  background-size: 10px 6px;
  background-repeat: no-repeat;
}
.tl-field .tl-phone > input, .tl-phone > input {
  width: 100%; min-width: 0; margin: 0; padding: 11px 14px;
  font: inherit; font-size: 15px; line-height: 1.4; color: var(--text);
  background: transparent; border: 0; border-radius: 0;
  box-shadow: none; outline: none;
}
.tl-field .tl-phone > select:focus-visible, .tl-phone > select:focus-visible,
.tl-field .tl-phone > input:focus-visible, .tl-phone > input:focus-visible {
  outline: 2px solid var(--cta, var(--accent)); outline-offset: -2px;
}
/* An option list is drawn by the platform and inherits nothing, so it needs
   its own colours or it is white on white on a dark theme in some browsers. */
.tl-phone > select option, .tl-phone > select optgroup {
  background: var(--bg2, var(--surface, #fff)); color: var(--text, #000);
}
@media (max-width: 380px) {
  .tl-phone { grid-template-columns: 6.2rem minmax(0, 1fr); }
  .tl-field .tl-phone > select, .tl-phone > select { padding-left: 10px; font-size: 13px; }
}
