/* Fonts — self-hosted through AssetMapper (latin + latin-ext cover the six
   locales); JetBrains Mono ships as a variable file, so one face per subset
   serves both 700 and 800. */

@font-face {
    font-family: 'DM Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/dm-mono-400-latin-x0OV0yC.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'DM Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/dm-mono-400-latin-ext-oevEWab.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'DM Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/dm-mono-500-latin-s5medZ3.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'DM Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/dm-mono-500-latin-ext-Qqb6l7e.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 700 800;
    font-display: swap;
    src: url("../fonts/jetbrains-mono-latin-UKAvhI1.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 700 800;
    font-display: swap;
    src: url("../fonts/jetbrains-mono-latin-ext-9ZLLWTT.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    /* Neutrals — only two of these are ever used as a page background. */
    --bg: #F7F2E6;
    --band: #EDE6D6;
    --line: #D3C8B2;
    --muted: #685E54;
    /* Muted text one step fainter still — disabled controls. */
    --muted-faint: #B6ABA0;
    --ink: #2F3237;
    --surface: #FFFFFF;
    --scrim: rgba(47, 50, 55, .55);
    --link: #4A55A5;

    --accent: #CE4049;
    --accent-shadow: #5D1D21;
    --focus: var(--accent);

    /* Accent palette — fact cards, hero-tile text, profile chips, share
       card, progress fills. Each --x pairs with a dark --on-x for text. */
    --red: #E0555F;
    --yellow: #FBB717;
    --slate: #343A4E;
    --green: #74CE86;
    --apricot: #F79340;
    --orange: #E0674A;
    --pink: #F0679B;
    --lavender: #9B8CFF;
    --teal: #2FBFA0;
    --blue: #5B90E8;

    --on-red: #2E080A;
    --on-yellow: #4A3200;
    --on-green: #08301A;
    --on-apricot: #4A2200;
    --on-orange: #360C02;
    --on-pink: #4E0F27;
    --on-lavender: #211A52;
    --on-teal: #06382E;
    --on-blue: #0B2547;

    /* Hero tiles — three pale hue-washes (sky / rose / mint), each with
       a deep same-family number. Hero-only, never on fact cards. */
    --sky: #DBE6F5;
    --rose: #F6DADC;
    --mint: #DAEFE7;

    --chip-active: #4A5058;

    /* One arrowhead corner (bottom-right) at four scales. */
    --r-sm: .25rem .25rem .75rem .25rem;
    --r-md: .5rem .5rem 1rem .5rem;
    --r-card: .5rem .5rem 1.5rem .5rem;
    --r-container: .75rem .75rem 1.5rem .75rem;
    --r-foot: 0 0 1.5rem .75rem;

    /* A bevel, never a drop shadow. */
    --bevel-neutral: inset 0 -.25rem 0 var(--line);
    --bevel-accent: inset 0 -.25rem 0 var(--accent-shadow);
    --press: translateY(.125rem);

    --tracking-caps: .14em;
    /* One fluid step for page gutters, section gaps and container padding —
       they are the same measure in the design, so they share one token. */
    --pad-fluid: clamp(1rem, 2.5vw, 1.5rem);
    /* One fluid step for every 1.5rem→2rem heading-sized value: card and
       tile numbers, and the "years" unit beside them. */
    --fs-value: clamp(1.5rem, 2.6vw, 2rem);
    /* Gap inside the card grids (hero tiles, facts) — 1rem on a wide screen,
       tightening to .5rem on a phone. Shared so the two grids always match. */
    --gap-grid: clamp(.5rem, 2vw, 1rem);

    --stripe-light: linear-gradient(-45deg, rgba(255, 255, 255, .4) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .4) 50%, rgba(255, 255, 255, .4) 75%, transparent 75%, transparent);
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    min-height: 100%;
    background: var(--bg);
    font-family: 'DM Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    color: var(--ink);
    -webkit-text-size-adjust: 100%;
}

a {
    color: var(--link);
    text-decoration: none;
}

a:hover {
    color: var(--ink);
}

button {
    font-family: inherit;
    border: none;
    background: none;
    cursor: pointer;
}

:focus-visible {
    outline: .1875rem solid var(--focus);
    outline-offset: .125rem;
}

/* Standard screen-reader-only clip; the 1px box is intrinsic to the
   technique, not a spacing value. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

input, select {
    font-family: inherit;
}

@keyframes stripes {
    from { background-position: 0 0; }
    to { background-position: 1rem 0; }
}

@keyframes pop {
    from { transform: translateY(1rem) scale(.98); opacity: .3; }
    to { transform: none; opacity: 1; }
}

@keyframes blink {
    0%, 62% { opacity: 1; }
    63%, 100% { opacity: .2; }
}

/* Layout */

.page {
    min-height: 100vh;
    background: var(--bg);
    position: relative;
    padding: 0 var(--pad-fluid) 2rem;
    display: flex;
    flex-direction: column;
}

.page__inner {
    max-width: 85rem;
    width: 100%;
    margin: 0 auto;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--pad-fluid);
}

/* Top bar */

.brand {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
    padding-top: var(--pad-fluid);
}

.brand__lockup {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-right: auto;
}

.brand__mark {
    height: 31px;
    width: auto;
    flex-shrink: 0;
}

.brand__wordmark {
    font: 500 1rem/1 'DM Mono', monospace;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink);
}

.brand__name {
    font: 800 1.25rem/1 'JetBrains Mono', monospace;
}

.brand__tld {
    opacity: .55;
}

/* Buttons */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    height: 3rem;
    padding: 0 1.25rem .25rem;
    border-radius: var(--r-md);
    border: none;
    font: 500 1rem/1 'DM Mono', monospace;
    text-decoration: none;
}

.btn:active {
    transform: var(--press);
}

.btn--ghost {
    background: var(--surface);
    color: var(--ink);
    box-shadow: var(--bevel-neutral);
}

.btn--ghost:hover {
    box-shadow: inset 0 -.25rem 0 var(--muted);
}

.btn--primary {
    background: var(--accent);
    color: var(--surface);
    box-shadow: var(--bevel-accent);
    padding: 0 clamp(.75rem, 1.5vw, 1rem) .25rem;
}

.btn--primary:hover {
    background: var(--surface);
    color: var(--ink);
    box-shadow: inset 0 -.25rem 0 var(--muted);
}

/* The share button is the one primary button sitting on white (the hero),
   where a white hover face would vanish — settle it on the sand band. */
.header__actions .btn--primary:hover {
    background: var(--band);
}

/* The keyboard ring is the accent colour, invisible on the accent fill —
   swap it for --ink on the buttons that carry that fill at rest. */
.btn--primary:focus-visible,
.modal__submit:focus-visible {
    outline-color: var(--ink);
}

.btn__icon {
    flex: none;
}

/* Language toggle — bordered and transparent, not a bevelled button. */

.lang-toggle {
    height: 2.25rem;
    padding: 0 .75rem;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: transparent;
    box-shadow: none;
    font: 500 .875rem/1 'DM Mono', monospace;
    letter-spacing: var(--tracking-caps);
    color: var(--muted);
}

.lang-toggle:hover {
    filter: none;
    background: transparent;
    box-shadow: none;
    color: var(--ink);
    border-color: var(--muted);
}

.lang-toggle:active {
    transform: none;
}

/* Profile chips */

.chips {
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: .75rem;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Headroom inside the scroller so a pressed chip and its focus ring
       aren't clipped, cancelled again outside so the chips still align with
       every other block and keep the page's single inter-block rhythm. */
    padding: .25rem .25rem .5rem;
    margin: -.25rem -.25rem -.5rem;
}

.chips::-webkit-scrollbar {
    display: none;
}

.chip {
    flex: none;
    display: flex;
}

.chip__button {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .5rem 1rem .75rem .5rem;
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: var(--bevel-neutral);
    cursor: pointer;
}

.chip--active .chip__button {
    background: var(--chip-active);
    box-shadow: inset 0 -.25rem 0 var(--ink);
}

/* Only the selectable (non-active) chips get a hover; the active one is
   disabled and is the current selection, not a target. */
.chip__button:not(:disabled):hover {
    box-shadow: inset 0 -.25rem 0 var(--muted);
}

.chip__button:disabled {
    cursor: default;
}

.chip__avatar {
    width: 2rem;
    height: 2rem;
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font: 500 .75rem/1 'DM Mono', monospace;
    flex: none;
}

.chip__name {
    font: 500 1rem/1 'DM Mono', monospace;
    color: var(--ink);
}

.chip--active .chip__name {
    color: var(--bg);
}

.chip-add {
    flex: none;
    /* Matches a chip's natural height (.5 + 2 avatar + .75 padding), so the
       button keeps its shape when it is the only thing in the row. */
    align-self: stretch;
    min-height: 3.25rem;
    display: flex;
    align-items: center;
    padding: 0 1.25rem;
    border-radius: var(--r-md);
    border: .125rem dashed var(--line);
    font: 500 1rem/1 'DM Mono', monospace;
    color: var(--muted);
    cursor: pointer;
}

.chip-add:hover {
    color: var(--ink);
    border-color: var(--muted);
}

/* Hero */

.stats {
    background: var(--surface);
    border-radius: var(--r-container);
    overflow: hidden;
    padding: var(--pad-fluid) var(--pad-fluid) 0;
    display: flex;
    flex-direction: column;
    gap: var(--pad-fluid);
}

.header {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: .75rem 1rem;
}

.header__title {
    display: flex;
    align-items: baseline;
    gap: .75rem;
    min-width: 0;
}

.header__title-name {
    font: 500 clamp(1.125rem, 1.8vw, 1.25rem)/1 'DM Mono', monospace;
    letter-spacing: -.02em;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.header__title-date {
    font: 500 .875rem/1 'DM Mono', monospace;
    color: var(--muted);
    white-space: nowrap;
}

.header__actions {
    display: flex;
    gap: .5rem;
    flex: none;
}

/* Hero body — the giant age sits beside the progress column above 900px
   and stacks above it below. Both are flex so the progress column keeps its
   own .75rem rhythm: as grid rows they would stretch to absorb the age
   block's height and blow those gaps out. */

.stats__main {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: clamp(1.5rem, 3vw, 2.5rem);
}

.stats__progress {
    flex: 1 1 15rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .75rem;
    padding-bottom: .5rem;
}

.stats__eyebrow {
    justify-self: start;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .75rem;
    border-radius: var(--r-sm);
    background: var(--band);
    font: 500 .75rem/1 'DM Mono', monospace;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--muted);
}

.stats__eyebrow::before {
    content: "";
    flex: none;
    width: .5rem;
    height: .5rem;
    background: var(--red);
    animation: blink 2s steps(1, end) infinite;
}

.stats__years {
    flex: none;
    display: flex;
    align-items: baseline;
    gap: .75rem;
}

.stats__years-num {
    font: 800 clamp(6.5rem, 22vw, 9.5rem)/.8 'JetBrains Mono', monospace;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

.stats__years-unit {
    font: 500 var(--fs-value)/1 'DM Mono', monospace;
    color: var(--muted);
}

.stats__since {
    font: 500 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
}

.progress {
    height: 1rem;
    background: var(--band);
    padding: .25rem;
    overflow: hidden;
}

.progress__bar {
    height: .5rem;
    background-color: var(--slate);
    background-image: var(--stripe-light);
    background-size: 1rem 1rem;
    animation: stripes 1s linear infinite;
    width: 0%;
    transition: width .3s ease-out;
}

.stats__next {
    font: 500 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
}

/* Hero tiles */

.stats__tiles {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--gap-grid);
}

/* Shared card shell — hero tiles and fact cards are the same box. */
.tile,
.fact {
    border-radius: var(--r-card);
    padding: 1.25rem 1.25rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.tile--sky { background: var(--sky); }
.tile--rose { background: var(--rose); }
.tile--mint { background: var(--mint); }

.tile__label,
.fact__label,
.field__label,
.date-field__label,
.share-tile__label,
.share-card__life-label {
    margin: 0;
    font: 500 .75rem/1 'DM Mono', monospace;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    text-wrap: balance;
}

.tile__value,
.fact__value {
    font: 700 var(--fs-value)/1.05 'JetBrains Mono', monospace;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}

.tile__note,
.fact__note {
    font: 400 .875rem/1.5 'DM Mono', monospace;
    margin-top: auto;
}

.tile--sky .tile__label,
.tile--sky .tile__note,
.tile--sky .tile__value { color: var(--on-blue); }

.tile--rose .tile__label,
.tile--rose .tile__note,
.tile--rose .tile__value { color: var(--on-red); }

.tile--mint .tile__label,
.tile--mint .tile__note,
.tile--mint .tile__value { color: var(--on-teal); }

/* Hero footer band — bleeds to the hero's edges through negative margins
   that cancel its horizontal padding. */

.stats__foot {
    margin: 0 calc(var(--pad-fluid) * -1);
    padding: 1rem 1.25rem 1.25rem;
    border: none;
    background: var(--band);
    border-radius: var(--r-foot);
    box-shadow: var(--bevel-neutral);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    font: 500 .875rem/1 'DM Mono', monospace;
    color: var(--muted);
    cursor: pointer;
}

.stats__foot .btn__icon {
    width: .875rem;
    height: .875rem;
}

/* Tip CTA */

.tip-cta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem 1rem;
    border-radius: var(--r-card);
    background: var(--band);
    padding: 1rem clamp(1rem, 2vw, 1.25rem);
}

/* The two translated halves are one flowing paragraph, not two lines. */
.tip-cta__text {
    display: inline;
    flex: 1;
    min-width: 15rem;
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
    text-wrap: pretty;
}

.tip-cta__text > span {
    display: inline;
}

.tip-cta__text > span + span::before {
    content: " ";
}

.tip-cta__action {
    flex: none;
}

/* Facts */

.divider {
    border: none;
    border-top: 1px solid var(--line);
    margin: 0;
}

.facts-title {
    margin: 0;
    font: 500 clamp(1.25rem, 2.4vw, 1.75rem)/1 'DM Mono', monospace;
    letter-spacing: -.02em;
    color: var(--ink);
}

.facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 19.5rem), 1fr));
    gap: var(--gap-grid);
}

.fact__label-row {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.fact__edit {
    margin: -.5rem -.5rem -.5rem auto;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .5rem;
    border: none;
    background: none;
    color: inherit;
    cursor: pointer;
    opacity: .8;
    transition: opacity .15s;
}

.fact__edit:hover {
    opacity: 1;
}

.fact__value--capitalize {
    text-transform: capitalize;
}

.fact__bar {
    height: .5rem;
    background: var(--band);
    overflow: hidden;
}

/* background-image only — the fill colour arrives inline from Twig. */
.fact__bar-fill {
    height: .5rem;
    width: 0%;
    background-image: var(--stripe-light);
    background-size: 1rem 1rem;
    animation: stripes 1s linear infinite;
}

.fact--red { background: var(--red); }
.fact--red .fact__label,
.fact--red .fact__note { color: var(--on-red); }
.fact--red .fact__value { color: #FFFFFF; }

.fact--yellow { background: var(--yellow); }
.fact--yellow .fact__label,
.fact--yellow .fact__note { color: var(--on-yellow); }
.fact--yellow .fact__value { color: var(--ink); }

.fact--ink { background: var(--slate); }
.fact--ink .fact__label,
.fact--ink .fact__note { color: #D7DDF0; }
.fact--ink .fact__value { color: var(--yellow); }

.fact--green { background: var(--green); }
.fact--green .fact__label,
.fact--green .fact__note { color: var(--on-green); }
.fact--green .fact__value { color: var(--ink); }

.fact--paper { background: var(--surface); }
.fact--paper .fact__label,
.fact--paper .fact__note { color: var(--muted); }
.fact--paper .fact__value { color: var(--ink); }

.fact--apricot { background: var(--apricot); }
.fact--apricot .fact__label,
.fact--apricot .fact__note,
.fact--apricot .fact__value { color: var(--on-apricot); }

.fact--orange { background: var(--orange); }
.fact--orange .fact__label,
.fact--orange .fact__note { color: var(--on-orange); }
.fact--orange .fact__value { color: #FFFFFF; }

.fact--pink { background: var(--pink); }
.fact--pink .fact__label,
.fact--pink .fact__note,
.fact--pink .fact__value { color: var(--on-pink); }

.fact--lavender { background: var(--lavender); }
.fact--lavender .fact__label,
.fact--lavender .fact__note,
.fact--lavender .fact__value { color: var(--on-lavender); }

.fact--teal { background: var(--teal); }
.fact--teal .fact__label,
.fact--teal .fact__note,
.fact--teal .fact__value { color: var(--on-teal); }

.fact--blue { background: var(--blue); }
.fact--blue .fact__label,
.fact--blue .fact__note { color: var(--on-blue); }
.fact--blue .fact__value { color: #FFFFFF; }

.fact--dark { background: var(--ink); }
.fact--dark .fact__label,
.fact--dark .fact__note { color: var(--line); }
.fact--dark .fact__value { color: #6DCFAE; }

/* FAQ */

.faq-list {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--gap-grid);
}

.faq-item {
    display: flex;
    flex-direction: column;
    gap: .75rem;
    padding: 1.25rem;
    background: var(--surface);
    border-radius: var(--r-card);
}

.faq-item__tag {
    display: flex;
    align-items: center;
    gap: .5rem;
    font: 500 .75rem/1 'DM Mono', monospace;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--muted);
}

.faq-item__tag::before {
    content: '';
    flex: none;
    width: .5rem;
    height: .5rem;
    border-radius: .125rem;
}

.faq-item--calc .faq-item__tag::before { background: var(--blue); }
.faq-item--time .faq-item__tag::before { background: var(--red); }
.faq-item--data .faq-item__tag::before { background: var(--ink); }
.faq-item--price .faq-item__tag::before { background: var(--yellow); }

.faq-item__question {
    margin: 0;
    font: 500 1.0625rem/1.4 'DM Mono', monospace;
    letter-spacing: -.01em;
    color: var(--ink);
}

.faq-item__answer {
    margin: 0;
    font: 400 .9375rem/1.6 'DM Mono', monospace;
    color: var(--muted);
    text-wrap: pretty;
}

/* Footer */

.footer {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .75rem 1rem;
    margin-top: auto;
}

.footer__text {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.footer__copyright,
.footer__visit {
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
    text-align: center;
}

.footer__copyright a {
    color: inherit;
    text-decoration: underline;
}

.footer__copyright a:hover {
    color: var(--ink);
}

/* Desktop pushes the copyright left and the visit line right; below 43.75em
   it stacks, copyright under the visit line (the .75rem row-gap applies). */
@media (max-width: 43.75em) {
    .footer {
        flex-direction: column-reverse;
        align-items: center;
    }
}

/* Overlay / modal */

.overlay {
    position: fixed;
    inset: 0;
    background: var(--scrim);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--pad-fluid);
    z-index: 40;
}

.overlay[hidden] {
    display: none;
}

.overlay > [data-profile-modal-target]:not([hidden]) {
    width: 100%;
    display: flex;
    justify-content: center;
}

.modal {
    width: 100%;
    max-width: 34rem;
    /* dvh, not vh: on mobile Safari 94vh is measured against the browser
       chrome hidden, so a modal sized to it can end up taller than what's
       actually visible once the address bar is showing — dvh tracks the
       real visible viewport instead, which is what was reading as the
       modal getting clipped top and bottom. */
    max-height: 94dvh;
    overflow: auto;
    background: var(--bg);
    border-radius: var(--r-container);
    padding: var(--pad-fluid);
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    animation: pop .2s ease-out;
}

.modal[hidden] {
    display: none;
}

/* The dialog takes focus on open only to be announced; it is not a
   control, so it shows no ring. */
.modal:focus {
    outline: none;
}

.modal__header {
    flex: none;
    display: flex;
    align-items: baseline;
    gap: .75rem;
}

.modal__title {
    margin: 0;
    font: 500 clamp(1.25rem, 2.4vw, 1.75rem)/1 'DM Mono', monospace;
    letter-spacing: -.02em;
    color: var(--ink);
}

.modal__close {
    margin-left: auto;
    font: 500 .875rem/1 'DM Mono', monospace;
    color: var(--muted);
    cursor: pointer;
}

.modal__close:hover {
    color: var(--ink);
}

.modal__body {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.modal__form {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

/* Profile form */

.field {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.field__label {
    color: var(--muted);
}

.field__optional {
    color: var(--muted);
}

.field__error {
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--red);
}

.input {
    width: 100%;
    height: 3.5rem;
    border-radius: var(--r-md);
    border: .125rem solid var(--line);
    background: var(--surface);
    padding: 0 1rem;
    font: 500 1rem/1 'DM Mono', monospace;
    color: var(--ink);
}

.input:focus {
    border-color: var(--focus);
}

.date-fields, .time-fields {
    display: flex;
    gap: .75rem;
    align-items: stretch;
}

.time-fields {
    max-width: 18.75rem;
}

.field-row {
    display: flex;
    gap: .75rem;
    flex-wrap: wrap;
}

.field-row .field {
    flex: 1;
    min-width: 12rem;
}

.date-field {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.date-field--year {
    flex: 1.6;
}

.date-field__input {
    width: 100%;
    height: 3.5rem;
    border-radius: var(--r-md);
    border: .125rem solid var(--line);
    background: var(--surface);
    text-align: center;
    font: 700 clamp(1.5rem, 5vw, 1.75rem)/1 'JetBrains Mono', monospace;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
    -moz-appearance: textfield;
}

.date-field__input:focus {
    border-color: var(--focus);
}

.date-field__label {
    color: var(--muted);
    text-align: center;
}

.privacy-note {
    flex: none;
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
    text-align: center;
}

.modal__submit {
    flex: none;
    width: 100%;
    height: 3.5rem;
    padding-bottom: .25rem;
    border-radius: var(--r-md);
    border: none;
    background: var(--accent);
    box-shadow: var(--bevel-accent);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font: 500 1rem/1 'DM Mono', monospace;
    color: var(--surface);
}

.modal__submit:hover {
    background: var(--surface);
    color: var(--ink);
    box-shadow: inset 0 -.25rem 0 var(--muted);
}

.modal__submit:active {
    transform: var(--press);
}

.modal__delete-row {
    flex: none;
    display: flex;
    justify-content: center;
}

.modal__delete {
    font: 500 .875rem/1 'DM Mono', monospace;
    color: var(--muted);
    text-decoration: underline;
    text-underline-offset: .25rem;
    cursor: pointer;
}

.modal__delete:hover {
    color: var(--ink);
}

/* Language modal */

.modal--lang {
    gap: 1rem;
}

.lang-list {
    flex: none;
    display: flex;
    flex-direction: column;
    gap: .75rem;
}

.lang-list__item {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .5rem 1rem .75rem .5rem;
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: var(--bevel-neutral);
    text-decoration: none;
    cursor: pointer;
}

.lang-list__item:hover {
    box-shadow: inset 0 -.25rem 0 var(--muted);
}

.lang-list__item--active {
    background: var(--chip-active);
    box-shadow: inset 0 -.25rem 0 var(--ink);
}

.lang-list__item--active:hover {
    box-shadow: inset 0 -.25rem 0 var(--ink);
    filter: brightness(1.12);
}

.lang-list__flag {
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: var(--r-sm);
    object-fit: cover;
}

.lang-list__name {
    font: 500 1rem/1 'DM Mono', monospace;
    color: var(--ink);
}

.lang-list__item--active .lang-list__name {
    color: var(--bg);
}

/* Tip modal */

/* The steps are flex columns, which would otherwise beat the [hidden]
   attribute the controller toggles them with. */
.tip-pick[hidden],
.tip-thanks[hidden] {
    display: none;
}

.tip-pick {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.tip-intro {
    margin: 0;
    font: 400 .9375rem/1.5 'DM Mono', monospace;
    color: var(--muted);
    text-wrap: pretty;
}

/* White selection card — counter, presets, free amount, then a total band. */
.tip-box {
    flex: none;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-radius: var(--r-container);
    overflow: hidden;
}

.tip-box__pick {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.25rem;
}

.tip-box__hint,
.tip-custom__label,
.tip-box__total-label {
    font: 500 .75rem/1 'DM Mono', monospace;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--muted);
}

.tip-counter {
    display: flex;
    align-items: center;
    gap: .75rem;
}

.tip-counter__btn {
    flex: none;
    width: 3rem;
    height: 3rem;
    padding-bottom: .25rem;
    border-radius: var(--r-md);
    background: var(--band);
    box-shadow: var(--bevel-neutral);
    font: 500 1.5rem/1 'DM Mono', monospace;
    color: var(--ink);
}

.tip-counter__btn:hover:not(:disabled) {
    filter: brightness(1.03);
}

.tip-counter__btn:active:not(:disabled) {
    transform: var(--press);
}

.tip-counter__btn:disabled {
    color: var(--muted-faint);
    cursor: default;
}

.tip-counter__display {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: .5rem;
}

.tip-counter__value {
    font: 800 clamp(2.5rem, 11vw, 3.25rem)/.9 'JetBrains Mono', monospace;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

.tip-counter__value--empty {
    color: var(--muted-faint);
}

/* No cap on the coffee count, but the fixed clamp() above only reads well
   up to 3 digits — beyond that it steps down a size per extra digit
   rather than wrap or spill past the +/- buttons. */
.tip-counter__value--md {
    font-size: clamp(1.75rem, 8vw, 2.5rem);
}

.tip-counter__value--lg {
    font-size: clamp(1.375rem, 6.5vw, 1.875rem);
}

.tip-counter__value--xl {
    font-size: clamp(1.125rem, 5.5vw, 1.5rem);
}

.tip-counter__unit {
    font: 500 1rem/1 'DM Mono', monospace;
    color: var(--muted);
}

.tip-presets {
    display: flex;
    gap: .5rem;
}

.tip-preset {
    flex: 1;
    height: 2.75rem;
    padding-bottom: .25rem;
    border-radius: var(--r-md);
    background: var(--band);
    box-shadow: var(--bevel-neutral);
    font: 500 .875rem/1 'DM Mono', monospace;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.tip-preset:hover {
    filter: brightness(1.06);
}

.tip-preset:active {
    transform: var(--press);
}

.tip-preset--active {
    background: var(--chip-active);
    box-shadow: inset 0 -.25rem 0 var(--ink);
    color: var(--bg);
}

.tip-custom {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .25rem .875rem;
    border: .125rem solid var(--line);
    border-radius: var(--r-sm);
}

/* Design: the border darkens once the field holds a value (and on focus). */
.tip-custom:focus-within,
.tip-custom:has(.tip-custom__input:not(:placeholder-shown)) {
    border-color: var(--muted);
}

.tip-custom__label {
    flex: none;
}

.tip-custom__input {
    flex: 1;
    min-width: 0;
    height: 2.75rem;
    border: none;
    background: transparent;
    text-align: right;
    font: 500 1.125rem/1 'DM Mono', monospace;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.tip-custom__input:focus {
    outline: none;
}

.tip-custom__suffix {
    flex: none;
    font: 500 1.125rem/1 'DM Mono', monospace;
    color: var(--muted);
}

.tip-box__total {
    display: flex;
    align-items: baseline;
    gap: .75rem;
    padding: 1rem 1.25rem 1.25rem;
    background: var(--band);
    border-radius: var(--r-foot);
    box-shadow: var(--bevel-neutral);
}

.tip-box__total-value {
    margin-left: auto;
    font: 700 1.5rem/1 'JetBrains Mono', monospace;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

.tip-submit {
    width: 100%;
    height: 3.5rem;
}

.tip-submit.is-loading {
    cursor: progress;
}

.tip-error {
    margin: 0;
    padding: .625rem .875rem;
    border-radius: var(--r-sm);
    background: var(--accent);
    color: var(--surface);
    font: 400 .8125rem/1.4 'DM Mono', monospace;
}

.tip-reassurance {
    margin: 0;
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
    text-align: center;
    text-wrap: pretty;
}

/* Step 2 — Stripe's checkout iframe (white background, no padding of its
   own) wrapped in a white card so its edges read as part of the modal. */
.tip-checkout {
    flex: none;
    min-height: 20rem;
    padding: 1rem;
    background: var(--surface);
    border-radius: var(--r-md);
    overflow: hidden;
}

.tip-back {
    align-self: flex-start;
    font: 500 .875rem/1 'DM Mono', monospace;
    color: var(--muted);
}

.tip-back:hover {
    color: var(--ink);
}

/* Step 3 */
.tip-thanks {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .75rem;
}

.tip-thanks__title {
    margin: 0;
    font: 500 1.125rem/1.4 'DM Mono', monospace;
    color: var(--ink);
}

.tip-thanks__text {
    margin: 0;
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
    text-wrap: pretty;
}

/* Share modal */

.share-card-box {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.share-card {
    flex: none;
    width: 100%;
    transform-origin: center;
    background: var(--surface);
    border-radius: var(--r-container);
    padding: 1.25rem 1.25rem 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.share-card__body {
    display: flex;
    flex-direction: column;
    gap: .75rem;
}

.share-card__identity {
    font: 500 clamp(1.125rem, 1.8vw, 1.25rem)/1.5 'DM Mono', monospace;
    letter-spacing: -.02em;
    color: var(--ink);
}

.share-card__years {
    display: flex;
    align-items: baseline;
    gap: .75rem;
}

.share-card__years-num {
    font: 800 clamp(3.75rem, 17vw, 5rem)/.8 'JetBrains Mono', monospace;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

.share-card__years-unit {
    font: 500 var(--fs-value)/1 'DM Mono', monospace;
    color: var(--muted);
}

.share-card__since {
    font: 500 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
}

.share-card__tiles {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .75rem;
    margin-top: 1rem;
}

/* Lets the two half-width tiles join their siblings in the parent grid. */
.share-card__row {
    display: contents;
}

.share-tile {
    border-radius: var(--r-card);
    padding: .75rem .75rem 1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.share-tile--seconds,
.share-card__life {
    grid-column: 1 / -1;
}

.share-tile--days { background: var(--sky); }
.share-tile--hours { background: var(--rose); }
.share-tile--seconds { background: var(--mint); }

.share-tile__value,
.share-card__life-value {
    font: 700 1.25rem/1.15 'JetBrains Mono', monospace;
    font-variant-numeric: tabular-nums;
}

.share-tile--days .share-tile__label,
.share-tile--days .share-tile__value { color: var(--on-blue); }
.share-tile--hours .share-tile__label,
.share-tile--hours .share-tile__value { color: var(--on-red); }
.share-tile--seconds .share-tile__label,
.share-tile--seconds .share-tile__value { color: var(--on-teal); }

.share-card__life {
    background: var(--band);
    border-radius: var(--r-card);
    padding: .75rem .75rem 1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.share-card__life-label {
    color: var(--muted);
}

.share-card__life-value {
    color: var(--ink);
}

.share-card__life-bar {
    height: .75rem;
    background: var(--surface);
    padding: .125rem;
    overflow: hidden;
}

/* Flat on purpose, unlike the bars on the page: the share card is a still
   image, and the stripe texture only reads as noise once frozen. The fill
   colour arrives inline from Twig. */
.share-card__life-bar-fill {
    height: .5rem;
    width: 0%;
}

.share-card__life-note {
    font: 400 .875rem/1.5 'DM Mono', monospace;
    color: var(--muted);
}

/* Ordered last so the wordmark reads as the card's footer band, while the
   markup keeps it first (its share-modal target must not move). */
.share-card__brand {
    order: 1;
    margin: 1rem -1.25rem 0;
    padding: 1rem 1.25rem 1.25rem;
    background: var(--band);
    border-radius: var(--r-foot);
    box-shadow: var(--bevel-neutral);
    text-align: center;
    font: 800 1rem/1 'JetBrains Mono', monospace;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink);
}

.share-actions {
    flex: none;
    display: flex;
    gap: .75rem;
    flex-wrap: wrap;
}

.share-actions .btn {
    flex: 1;
    min-width: 8.75rem;
    height: 3.5rem;
    padding-bottom: .25rem;
}

/* Breakpoints */

/* On small phones a floating card leaves too little room for anything
   tall (the profile form, the embedded Stripe form…) — let it take the
   whole screen instead of clipping against max-height. */
@media (max-width: 30em) {
    .overlay {
        padding: 0;
    }

    .modal {
        max-width: none;
        max-height: none;
        height: 100dvh;
        border-radius: 0;
        padding:
            max(var(--pad-fluid), env(safe-area-inset-top))
            max(var(--pad-fluid), env(safe-area-inset-right))
            max(var(--pad-fluid), env(safe-area-inset-bottom))
            max(var(--pad-fluid), env(safe-area-inset-left));
    }
}

@media (max-width: 56.25em) {
    .stats {
        gap: 1.25rem;
    }

    .stats__main {
        flex-direction: column;
        align-items: stretch;
        gap: .75rem;
    }

    .stats__progress {
        flex: 0 0 auto;
        padding-bottom: 0;
    }

    /* Not enough width for three tiles across: days and hours share the
       top row, the long seconds number gets its own below. */
    .stats__tiles {
        grid-template-columns: 1fr 1fr;
    }

    .tile--full {
        grid-column: 1 / -1;
    }
}

/* The FAQ grid drops columns sooner than the rest of the page — at four
   across, a card gets cramped well before the page's own 56.25em step. */
@media (max-width: 75em) {
    .faq-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Narrower still than the 75em step above — must come after it so this
   one wins the cascade at small phone widths, where both queries match. */
@media (max-width: 43.75em) {
    .faq-list {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 48.75em) {
    /* Too tight for badge + name + button on one line: the badge and the
       share icon share the top row, the name gets the full width below. */
    .header {
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
    }

    .stats__eyebrow {
        grid-column: 1;
        grid-row: 1;
        justify-self: start;
    }

    .header__actions {
        grid-column: 2;
        grid-row: 1;
    }

    .header__title {
        grid-column: 1 / -1;
        grid-row: 2;
    }

    /* Share collapses to its icon: no fill, no bevel, accent glyph. */
    .header__actions .btn--primary {
        width: 2.75rem;
        height: 2.75rem;
        padding: .25rem;
        border-radius: .25rem;
        background: transparent;
        box-shadow: none;
        color: var(--accent);
    }

    .header__actions .btn--primary:hover {
        background: transparent;
        color: var(--ink);
        box-shadow: none;
    }

    .header__actions .btn--primary .btn__icon {
        transform: scale(1.375);
    }

    .header__actions .btn__label {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .progress__bar,
    .fact__bar-fill {
        animation: none;
    }

    .stats__eyebrow::before {
        animation: none;
    }

    .modal {
        animation: none;
    }
}
