/* ==========================================================================
   Alessandro Discalzi — portfolio
   Hand-written, dependency-free stylesheet (no Bootstrap, no jQuery).
   Print rules live in print.css.
   ========================================================================== */

/* ---------- Design tokens ---------- */
:root {
    --bg:            #ffffff;
    --bg-alt:        #f6f7f9;
    --surface:       #ffffff;
    --surface-2:     #f1f3f6;
    --text:          #10151f;
    --text-muted:    #5b6676;
    --border:        #e3e7ed;
    --accent:        #c2410c;
    --accent-strong: #9a3412;
    --accent-soft:   #fef1e9;
    --accent-ring:   rgba(194, 65, 12, .28);
    --shadow:        0 1px 2px rgba(16, 21, 31, .05), 0 8px 24px -12px rgba(16, 21, 31, .18);
    --shadow-lg:     0 2px 4px rgba(16, 21, 31, .06), 0 24px 48px -24px rgba(16, 21, 31, .35);

    --radius:    14px;
    --radius-sm: 9px;
    --wrap:      1120px;

    --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
                 "Liberation Mono", monospace;

    --step: clamp(3.5rem, 7vw, 6rem);   /* vertical section rhythm */
}

:root[data-theme="dark"] {
    --bg:            #0b1120;
    --bg-alt:        #0f1626;
    --surface:       #121a2b;
    --surface-2:     #182136;
    --text:          #e6ebf3;
    --text-muted:    #9aa8bd;
    --border:        #22304a;
    --accent:        #fb923c;
    --accent-strong: #fdba74;
    --accent-soft:   rgba(251, 146, 60, .12);
    --accent-ring:   rgba(251, 146, 60, .32);
    --shadow:        0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -12px rgba(0, 0, 0, .7);
    --shadow-lg:     0 2px 4px rgba(0, 0, 0, .45), 0 24px 48px -24px rgba(0, 0, 0, .8);
    color-scheme: dark;
}

/* ---------- Reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
    scroll-behavior: smooth;
    /* offset for the sticky header when jumping to an anchor */
    scroll-padding-top: 84px;
    -webkit-text-size-adjust: 100%;
}

/* ---------- Slide deck ----------
   Exactly one section on screen at a time: slides are stacked in the same
   place and only the active one is visible, so neighbours can never peek in
   at the edges. Long slides (Resume, Projects) scroll internally, and the
   deck advances only once that inner scroll reaches its end.

   Every rule here is gated on .is-enhanced, which main.js adds. Without it
   the page stays an ordinary scrolling document: the deck depends on JS to
   mark a slide current, so ungated these rules hid *everything* when scripts
   did not run — blank for Bing, LinkedIn's preview bot and anything else that
   does not execute JS, and blank for visitors if main.js ever fails. */
.deck:not(.is-enhanced) { padding-top: 68px; }   /* clear the fixed header */

.deck.is-enhanced {
    position: relative;
    height: 100svh;
    overflow: hidden;
    perspective: 1500px;
    perspective-origin: 50% 50%;
}

/* Child combinator so these win over the later `.section` padding rule. */
.deck.is-enhanced > .slide {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
    /* `safe` matters: with plain `center`, content taller than the slide
       overflows equally in both directions and the top is clipped out of the
       scroll range — the Resume heading becomes unreachable. `safe` falls
       back to flex-start as soon as it would overflow. */
    justify-content: safe center;
    /* clear the fixed header */
    padding-block: calc(68px + clamp(1.5rem, 4vw, 3rem)) clamp(1.5rem, 4vw, 3rem);
    backface-visibility: hidden;
    transform-style: preserve-3d;
    will-change: transform, opacity;
}

/* Inactive slides are fully removed from view and from the tab order. */
.deck.is-enhanced .slide:not(.is-current) {
    visibility: hidden;
    pointer-events: none;
}

.deck.is-enhanced .slide.is-current { visibility: visible; z-index: 2; }
/* the outgoing slide stays painted for the length of the transition */
.deck.is-enhanced .slide.is-leaving { visibility: visible; z-index: 1; }

/* ---------- Slide transition ----------
   The deck tumbles like a die being rolled: the outgoing face pitches away
   on the X axis while the incoming face rolls up into place. */
/* --slide-dur must match DURATION in main.js */
:root { --slide-dur: .62s; --slide-ease: cubic-bezier(.22, .75, .28, 1); }

@keyframes tumble-in-down {
    from { opacity: 0; transform: translateY(58%) rotateX(-62deg) scale(.84); }
    to   { opacity: 1; transform: none; }
}
@keyframes tumble-out-down {
    from { opacity: 1; transform: none; }
    to   { opacity: 0; transform: translateY(-58%) rotateX(62deg) scale(.84); }
}
@keyframes tumble-in-up {
    from { opacity: 0; transform: translateY(-58%) rotateX(62deg) scale(.84); }
    to   { opacity: 1; transform: none; }
}
@keyframes tumble-out-up {
    from { opacity: 1; transform: none; }
    to   { opacity: 0; transform: translateY(58%) rotateX(-62deg) scale(.84); }
}

@media (prefers-reduced-motion: no-preference) {
    .slide.in-down  { animation: tumble-in-down  var(--slide-dur) var(--slide-ease) both; }
    .slide.out-down { animation: tumble-out-down var(--slide-dur) var(--slide-ease) both; }
    .slide.in-up    { animation: tumble-in-up    var(--slide-dur) var(--slide-ease) both; }
    .slide.out-up   { animation: tumble-out-up   var(--slide-dur) var(--slide-ease) both; }
}

/* Progress dots */
.deck-nav {
    position: fixed;
    right: clamp(.75rem, 2vw, 1.5rem);
    top: 50%;
    transform: translateY(-50%);
    z-index: 90;
    display: flex;
    flex-direction: column;
    gap: .7rem;
    list-style: none;
}
.deck-nav button {
    display: block;
    width: 10px; height: 10px; padding: 0;
    border-radius: 50%;
    border: 1px solid var(--text-muted);
    background: transparent;
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease, transform .2s ease;
}
.deck-nav button[aria-current="true"] {
    background: var(--accent);
    border-color: var(--accent);
    transform: scale(1.35);
}
.deck-nav button:hover { border-color: var(--accent); }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { line-height: 1.2; margin: 0 0 .5em; font-weight: 700; letter-spacing: -.02em; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
ul, ol { margin: 0; padding: 0; }
img { max-width: 100%; height: auto; display: block; }

a {
    color: var(--accent);
    text-decoration-color: var(--accent-ring);
    text-underline-offset: 3px;
    transition: color .15s ease;
}
a:hover { color: var(--accent-strong); }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 4px;
}

.visually-hidden {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

.skip-link {
    position: absolute; left: 12px; top: -60px; z-index: 200;
    background: var(--accent); color: #fff; padding: .6rem 1rem;
    border-radius: var(--radius-sm); font-weight: 600; text-decoration: none;
    transition: top .18s ease;
}
.skip-link:focus { top: 12px; color: #fff; }

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }

.ico { width: 1.15em; height: 1.15em; flex: none; }

/* print.css flips these two */
.print-only { display: none; }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; gap: .55rem;
    padding: .68rem 1.25rem;
    border: 1px solid transparent;
    border-radius: 999px;
    font: inherit; font-weight: 600; font-size: .95rem;
    text-decoration: none; cursor: pointer;
    transition: transform .12s ease, background-color .15s ease,
                border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
    background: var(--accent); color: #fff; box-shadow: var(--shadow);
}
.btn-primary:hover { background: var(--accent-strong); color: #fff; }
:root[data-theme="dark"] .btn-primary { color: #1a1005; }
:root[data-theme="dark"] .btn-primary:hover { color: #1a1005; }

.btn-outline {
    background: transparent; color: var(--text); border-color: var(--border);
}
.btn-outline:hover { border-color: var(--accent); color: var(--accent); }

.btn-ghost {
    background: var(--surface-2); color: var(--text);
    border-color: var(--border); padding: .5rem 1rem; font-size: .9rem;
}
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }

.icon-btn {
    display: inline-grid; place-items: center;
    width: 40px; height: 40px; padding: 0;
    background: var(--surface-2); color: var(--text);
    border: 1px solid var(--border); border-radius: 999px;
    cursor: pointer; transition: border-color .15s ease, color .15s ease;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent); }
.icon-btn .ico { width: 18px; height: 18px; }

/* sun in light mode, moon in dark mode */
.theme-toggle .ico-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .ico-sun  { display: none; }
:root[data-theme="dark"] .theme-toggle .ico-moon { display: block; }

/* ---------- Top bar ---------- */
/* Fixed rather than sticky: the page itself no longer scrolls — each slide
   scrolls internally — so there is nothing for `sticky` to stick to. */
.topbar {
    position: fixed; top: 0; left: 0; right: 0; z-index: 100;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid transparent;
    transition: border-color .2s ease, box-shadow .2s ease;
}
.topbar.is-stuck { border-bottom-color: var(--border); box-shadow: var(--shadow); }

.topbar-inner {
    display: flex; align-items: center; gap: 1rem;
    min-height: 68px;
}

.brand {
    display: flex; align-items: center; gap: .65rem;
    color: var(--text); text-decoration: none; margin-right: auto;
}
.brand img { border-radius: 50%; width: 36px; height: 36px; object-fit: cover; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-text strong { font-size: .95rem; letter-spacing: -.01em; }
.brand-text small { color: var(--text-muted); font-size: .78rem; }

.site-nav { display: flex; gap: .25rem; }
.site-nav a {
    position: relative;
    padding: .5rem .85rem; border-radius: var(--radius-sm);
    color: var(--text-muted); text-decoration: none;
    font-size: .93rem; font-weight: 500;
}
.site-nav a:hover { color: var(--text); background: var(--surface-2); }
.site-nav a.is-active { color: var(--accent); }
.site-nav a.is-active::after {
    content: ""; position: absolute; left: .85rem; right: .85rem; bottom: .25rem;
    height: 2px; background: var(--accent); border-radius: 2px;
}

.topbar-actions { display: flex; align-items: center; gap: .5rem; }

.nav-toggle {
    display: none;
    width: 42px; height: 42px; padding: 0;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); cursor: pointer;
}
.nav-toggle span {
    display: block; width: 18px; height: 2px; margin: 3.5px auto;
    background: var(--text); border-radius: 2px;
    transition: transform .2s ease, opacity .2s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* ---------- Hero ---------- */
.hero {
    position: relative;
    padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(2rem, 5vw, 4rem);
    background:
        radial-gradient(820px 420px at 50% 6%, var(--accent-soft), transparent 65%),
        linear-gradient(180deg, var(--bg-alt), var(--bg));
    border-bottom: 1px solid var(--border);
    overflow: hidden;
}

.hero-inner {
    display: flex;
    justify-content: center;
    text-align: center;
}

/* Sized to the source: avatar_head.jpg is 360px, so 160px stays within native
   resolution even at 2x device pixel ratio. Going bigger would upscale and
   soften it — the photo simply has no more detail to give. */
.hero-avatar {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    object-fit: cover;
    margin: 0 auto 1.6rem;
    border: 4px solid var(--surface);
    box-shadow: 0 0 0 1px var(--border), var(--shadow-lg);
}

.eyebrow {
    margin: 0 0 .35rem;
    color: var(--accent); font-weight: 600; font-size: .9rem;
    letter-spacing: .12em; text-transform: uppercase;
}

.hero h1 {
    margin: 0 0 .15em;
    font-size: clamp(2.1rem, 6.2vw, 4rem);
    letter-spacing: -.035em;
    text-wrap: balance;
}

.hero-role {
    margin: 0 0 1.1rem;
    font-family: var(--font-mono);
    font-size: clamp(1rem, 2.2vw, 1.2rem);
    color: var(--text-muted);
}

.hero-lede {
    max-width: 54ch; margin: 0 auto 1.9rem;
    font-size: clamp(1rem, 1.6vw, 1.1rem); color: var(--text-muted);
}

.hero-actions {
    display: flex; flex-wrap: wrap; gap: .75rem;
    justify-content: center; margin-bottom: 1.75rem;
}

.social-row { display: flex; gap: .5rem; list-style: none; justify-content: center; }
.social-row a {
    display: grid; place-items: center;
    width: 42px; height: 42px; border-radius: 999px;
    color: var(--text-muted); background: var(--surface);
    border: 1px solid var(--border);
    transition: color .15s ease, border-color .15s ease, transform .15s ease;
}
.social-row a:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-2px); }
.social-row .ico { width: 18px; height: 18px; }
.social-row-sm a { width: 38px; height: 38px; }

/* ---------- Sections ---------- */
.section { padding: var(--step) 0; }
.section-alt { background: var(--bg-alt); }
/* Edge borders make no sense on a full-screen slide. */
.deck > .section-alt { border-block: 0; }

.section-title {
    font-size: clamp(1.75rem, 3.4vw, 2.4rem);
    margin-bottom: 2.25rem;
}
.section-title .accent { color: var(--accent); }

.section-lede { color: var(--text-muted); margin: 0; }

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: clamp(1.25rem, 2.5vw, 1.75rem);
    box-shadow: var(--shadow);
}

.card h3 {
    font-size: 1.15rem; margin-bottom: 1.1rem;
    padding-bottom: .6rem; border-bottom: 1px solid var(--border);
}

.hint { color: var(--text-muted); font-size: .85rem; }

/* ---------- About ---------- */
.about-grid {
    display: grid; gap: 1.5rem;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    align-items: start;
}
.about-bio p { color: var(--text-muted); }

.facts { margin: 0; display: grid; gap: .9rem; }
.facts > div { display: grid; gap: .1rem; }
.facts dt {
    font-size: .74rem; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--text-muted);
}
.facts dd { margin: 0; font-size: .95rem; overflow-wrap: anywhere; }
.about-facts .social-row { margin-top: 1.4rem; }

/* ---------- Resume ---------- */
.resume-grid {
    display: grid; gap: 1.5rem;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
}
.resume-col { display: grid; gap: 1.5rem; }

.timeline { list-style: none; }
.timeline > li {
    position: relative;
    padding: 0 0 1.4rem 1.35rem;
    border-left: 2px solid var(--border);
}
.timeline > li:last-child { padding-bottom: 0; border-left-color: transparent; }
.timeline > li::before {
    content: "";
    position: absolute; left: -6px; top: .45rem;
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 4px var(--bg);
}
.timeline h4 { font-size: 1rem; margin-bottom: .15rem; color: var(--text); }
.timeline .at { font-weight: 500; color: var(--text-muted); }
.timeline .formerly { font-weight: 400; font-size: .85em; color: var(--text-muted); }
.timeline .when {
    margin: 0 0 .45rem;
    font-family: var(--font-mono); font-size: .8rem;
    color: var(--text-muted); letter-spacing: .01em;
}
.timeline p { font-size: .93rem; color: var(--text-muted); }
.timeline .meta { font-size: .85rem; margin-top: .35rem; }

.bullets { list-style: none; display: grid; gap: .4rem; }
.bullets li {
    position: relative; padding-left: 1rem;
    font-size: .93rem; color: var(--text-muted);
}
.bullets li::before {
    content: ""; position: absolute; left: 0; top: .62em;
    width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
}

.skill-heading {
    font-size: .78rem; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--accent);
    margin: 1.5rem 0 .6rem;
}
.skill-heading:first-of-type { margin-top: 0; }
.skill-heading + .hint { margin: -.35rem 0 .6rem; }

.chips { display: flex; flex-wrap: wrap; gap: .4rem; list-style: none; }
.chips li {
    padding: .25rem .65rem;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 999px; font-size: .82rem; color: var(--text-muted);
    white-space: nowrap;
}
.soft-skills { font-size: .9rem; color: var(--text-muted); }

.langs { list-style: none; display: grid; gap: 1rem; }
.lang-row {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 1rem; margin-bottom: .35rem; font-size: .95rem;
}
.lang-level { color: var(--text-muted); font-size: .82rem; }
.meter {
    height: 6px; border-radius: 999px;
    background: var(--surface-2); border: 1px solid var(--border);
    overflow: hidden;
}
.meter i {
    display: block; height: 100%;
    background: linear-gradient(90deg, var(--accent), var(--accent-strong));
}

/* ---------- Projects ---------- */
.projects-head {
    display: flex; flex-wrap: wrap; align-items: center;
    justify-content: space-between; gap: 1rem; margin-bottom: 1.75rem;
}
.search input {
    width: min(280px, 100%);
    padding: .6rem .95rem;
    font: inherit; font-size: .92rem;
    color: var(--text); background: var(--surface);
    border: 1px solid var(--border); border-radius: 999px;
}
.search input::placeholder { color: var(--text-muted); }
.search input:focus-visible { border-color: var(--accent); outline-offset: 1px; }

.repo-list {
    display: grid; gap: 1.25rem; list-style: none;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.repo {
    display: flex; flex-direction: column;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 1.25rem;
    box-shadow: var(--shadow);
    transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.repo:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--accent-ring); }
.repo.is-hidden { display: none; }
/* Repo names are unspaced identifiers and can be long enough to blow out the
   grid on narrow screens. */
.repo h3 {
    font-size: 1.02rem; margin-bottom: .4rem; padding: 0; border: 0;
    overflow-wrap: anywhere;
}
.repo h3 a { color: var(--text); text-decoration: none; }
.repo h3 a:hover { color: var(--accent); }
.repo-desc {
    font-size: .9rem; color: var(--text-muted);
    flex: 1 1 auto; margin-bottom: 1rem; overflow-wrap: anywhere;
}
.repo-meta {
    display: flex; flex-wrap: wrap; align-items: center; gap: .9rem;
    font-size: .8rem; color: var(--text-muted); margin-bottom: 1rem;
}
.repo-meta span { display: inline-flex; align-items: center; gap: .3rem; }
.repo-meta .ico { width: 13px; height: 13px; }
.lang-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--text-muted); }
.repo-links { display: flex; flex-wrap: wrap; gap: .5rem; }
.repo-links .btn { padding: .42rem .9rem; font-size: .82rem; }

.repo-status {
    grid-column: 1 / -1;
    padding: 1.5rem; text-align: center;
    color: var(--text-muted); font-size: .93rem;
}
.projects-foot { margin-top: 2rem; text-align: center; }

/* ---------- Contact ---------- */
/* No form any more: the section leads with the email address itself. */
.contact-lede { max-width: 46ch; margin: 0 0 1.75rem; }
.contact-cta { margin: 0 0 2.5rem; }
.contact-cta .btn { font-size: 1.02rem; padding: .85rem 1.6rem; }
.contact-cta .btn span { overflow-wrap: anywhere; }
.contact-hint { margin-top: 2rem; }

.contact-list {
    list-style: none;
    display: grid; gap: 1.1rem;
    grid-template-columns: repeat(auto-fit, minmax(220px, max-content));
}
.contact-list li { display: flex; gap: .85rem; align-items: flex-start; }
.contact-list .ico { color: var(--accent); margin-top: .25rem; width: 19px; height: 19px; }
.contact-list div { display: grid; gap: .1rem; min-width: 0; }
.contact-list span {
    font-size: .74rem; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--text-muted);
}
.contact-list a { overflow-wrap: anywhere; }

/* ---------- Footer ---------- */
.site-footer {
    padding: 2rem 0;
    background: var(--bg); border-top: 1px solid var(--border);
    color: var(--text-muted); font-size: .88rem;
}

/* Inside the deck the footer rides along at the bottom of the Contact slide.
   At full padding that slide overflowed by ~23px — just enough to become
   scrollable, so swiping up spent the first gesture on those few pixels
   instead of changing section. Trimming it lets Contact fit exactly. */
.deck .site-footer {
    padding: 1.1rem 0 0;
    background: transparent;
    margin-top: auto;
}
.footer-inner {
    display: flex; flex-wrap: wrap; gap: 1rem;
    align-items: center; justify-content: space-between;
}
.footer-inner p { margin: 0; }
.footer-links { display: flex; gap: 1.25rem; }
.footer-links a { color: var(--text-muted); text-decoration: none; }
.footer-links a:hover { color: var(--accent); }

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
    .resume-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .about-grid { grid-template-columns: 1fr; }
}

@media (max-width: 780px) {
    html { scroll-padding-top: 76px; }

    .nav-toggle { display: block; order: 3; }
    .topbar-actions { order: 2; }

    .site-nav {
        order: 4; flex-basis: 100%; flex-direction: column; gap: .15rem;
        max-height: 0; overflow: hidden;
        transition: max-height .25s ease, opacity .2s ease;
        opacity: 0;
    }
    .site-nav.is-open { max-height: 320px; opacity: 1; padding-bottom: .85rem; }
    .site-nav a { padding: .7rem .85rem; }
    .site-nav a.is-active::after { display: none; }
    .topbar-inner { flex-wrap: wrap; padding-block: .5rem; }

    .hero-avatar { width: 128px; height: 128px; }

    /* Keep brand, actions and the menu button on a single row: without this
       the toggle wraps onto a line of its own. The brand must be allowed to
       shrink (flex items default to min-width:auto and refuse to). */
    .brand-text small { display: none; }
    .btn-print span { display: none; }
    .btn-print { padding: .5rem .7rem; }
    .topbar-inner { gap: .5rem; }
    .brand { min-width: 0; }
    .brand-text { min-width: 0; }
    /* A wrapping flex container wraps items before it shrinks them, so the
       brand's base size has to be capped outright, not just made shrinkable. */
    .brand-text strong {
        max-width: 33vw;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
}

/* Below this the name no longer fits beside the controls at all — and it is
   repeated in the hero immediately underneath, so the mark alone is enough. */
@media (max-width: 430px) {
    .brand-text { display: none; }

    .resume-grid { grid-template-columns: 1fr; }
    .projects-head { flex-direction: column; align-items: stretch; }
    .search input { width: 100%; }
}

/* ---------- Section reveal ----------
   Driven entirely by CSS scroll timelines. Everything lives inside @supports,
   so a browser without them simply shows the content — the animation can
   never be the reason something is invisible. No JS is involved, so it also
   survives a script failure. */
/* There is deliberately no separate per-element reveal here. Staggering the
   children ran *after* the slide transition, so the section arrived and then
   its contents blinked out and back in. The tumble carries the whole slide as
   one solid face instead. */

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; scroll-snap-type: none; }
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}
