/* The homepage (public/index.html). Built on tokens.css and site.css
   (header, buttons, fields, footer); everything here is scoped to .sl-home.
   The world is the brand's paper collage: the torn orange scrap says what
   signing up gets you, a paper slip tucked under it takes the email, a torn
   white card is the pass being made out, a ruled notebook sheet holds the two
   things to do before launch, and the brand's ink doodles sit only where they
   mean something. */

/* Caveat, the handwriting, is declared in flow.css, which loads first. */

.sl-home {
  --sl-gutter: var(--tud-space-4);
  --sl-orange: var(--tud-color-accent-base);
  --sl-ink: var(--tud-color-ramp-neutral-950);
  --sl-paper: var(--tud-color-bg-surface);
  --sl-rule: #DCE6F2;
  --sl-margin: rgba(235, 80, 29, 0.5);
  --sl-shadow: rgba(20, 20, 18, 0.2);
  --sl-note: var(--tud-color-accent-text-on-light);
  --sl-hand: 'Caveat', 'Segoe Print', 'Bradley Hand', cursive;
  /* Lifts the crumple back toward clean paper: creases, not smudges. */
  --sl-wash: rgba(255, 255, 255, 0.3);
}
[data-theme="dark"] .sl-home {
  --sl-rule: #2B2925;
  --sl-margin: rgba(255, 92, 38, 0.42);
  --sl-shadow: rgba(0, 0, 0, 0.55);
  --sl-note: var(--tud-color-ramp-accent-300);
  --sl-wash: rgba(28, 26, 23, 0.2);
}

.sl-home ::selection { background: var(--tud-color-ramp-accent-200); color: var(--sl-ink); }
.sl-home { caret-color: var(--sl-orange); }
.sl-home main p { margin: 0; }
.sl-home main h1,
.sl-home main h2,
.sl-home main h3 { margin: 0; }
/* Sign in stays in the header at every width: the page's second door. */
.sl-home .nav-signin { display: inline-flex; }
/* Signed in, app.js swaps it for the My account menu button, which it styles
   primary. Here the slip's button is the one orange action, so the header
   control stays secondary. */
.sl-home .nav-account-btn {
  color: var(--tud-color-text-primary);
  background: var(--tud-color-bg-surface);
  border-color: var(--tud-color-border-strong);
}
.sl-home .nav-account-btn:hover { background: var(--tud-color-bg-sunken); border-color: var(--tud-color-text-muted); box-shadow: none; }

/* The page clips sideways at the viewport's edges, not at any box inside
   it: the scrap bleeds into the gutters and turns while it lands, the
   megaphone overhangs, and the pass can be dragged anywhere its lanyard
   reaches, over the rest of the page and out past its side, without ever
   widening the page or being cut off by its column. clip, unlike hidden,
   makes no scroll container. */
:root:has(> body.sl-home) { overflow-x: clip; }
.sl-main {
  /* The box spans the gutters so the scrap can bleed into them. */
  max-width: calc(var(--site-content) + var(--sl-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--sl-gutter);
  padding-top: clamp(24px, 4vw, 48px);
  padding-bottom: clamp(48px, 6vw, 80px);
}

/* ---------- the hero: the scrap, the slip, the pass ---------- */

.sl-hero { display: grid; grid-template-columns: minmax(0, 1fr); }

.sl-scrap-wrap {
  --sl-tilt: -2deg;
  position: relative;
  z-index: 1;
  margin-inline: calc(var(--tud-space-2) * -1);
  transform: rotate(var(--sl-tilt));
}
.sl-scrap {
  position: relative;
  /* The kit's torn orange strip (collage kit 02-torn-scraps/strip-orange.png,
     its paper tinted to brand #FF5C26 with the pale torn core kept): a real
     tear with grain and a soft baked shadow. It stretches to the box; the
     transparent shadow margin at the bottom is why the padding is uneven, and
     the padding keeps every word on the paper, clear of the torn edges. */
  padding: clamp(58px, 7vw, 72px) clamp(24px, 4.6vw, 64px) clamp(56px, 8.4vw, 96px);
  color: var(--sl-ink);
  background: url('/assets/img/soon/scrap-orange.webp?v=2') center / 100% 100% no-repeat;
}
.sl-scrap h1 {
  position: relative;
  z-index: 1;
  max-width: 22ch;
  font-size: clamp(34px, 3.2vw + 22px, 72px);
  font-weight: 800;
  line-height: 0.98;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.sl-lede {
  position: relative;
  z-index: 1;
  max-width: 46ch;
  margin-top: clamp(12px, 1.6vw, 20px) !important;
  font-size: clamp(16px, 1.3vw, 19px);
  font-weight: 500;
  line-height: 1.5;
  text-wrap: pretty;
}

.sl-tape {
  --sl-tape-w: clamp(92px, 15vw, 176px);
  position: absolute;
  z-index: 2;
  /* Straddle the torn top edge so the tape holds the paper: under the tape
     the strip's edge sits about a tenth of the way down the stretched image,
     so the tape's middle goes there, half on the paper and half off. */
  top: calc(10% - var(--sl-tape-w) * 81 / 440);
  left: clamp(14px, 6vw, 72px);
  width: var(--sl-tape-w);
  aspect-ratio: 220 / 81;
  transform: rotate(-5deg);
  /* Collage kit 06-tape/tape-orange-stripes.png: translucent washi, torn
     ends, a touch see-through so the torn edge reads under it. */
  opacity: 0.86;
  filter: drop-shadow(0 2px 3px var(--sl-shadow));
  background: url('/assets/img/soon/tape-stripes.webp') center / contain no-repeat;
}

/* Collage kit 05-halftone-cutouts/megaphone-ink: a real photo printed as a
   halftone cut-out with its sticker border, biting the scrap's corner. */
.sl-megaphone {
  position: absolute;
  z-index: 3;
  /* Low enough that the up dash of the burst stays under the header line even
     at the end of its travel, and in from the edge far enough for the dashes
     to clear the page clip. */
  top: -27px;
  right: 24px;
  width: clamp(84px, 22vw, 236px);
  transform: rotate(11deg);
  transform-origin: 40% 70%;
  pointer-events: none;
}
.sl-megaphone-img { display: block; width: 100%; height: auto; }
/* The sound: the megaphone doodle's burst, three short straight dashes in
   the doodles' ink line (cream in the dark theme) fanning from the bell's
   mouth, each shooting out from it along its own ray. The SVG lies exactly
   over the cut-out in its own pixel space (the geometry is in the markup),
   so it turns with it and scales with it. Still and faint when motion is
   off. */
.sl-burst {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  color: var(--tud-color-text-primary);
}
/* Each dash scales from its inner end; its group has already turned its ray
   to +x, so a translateX is a move outward along that ray. */
.sl-burst-line { opacity: 0.35; transform-box: fill-box; transform-origin: 0 50%; }

/* ---------- the sign-up slip ----------
   A paper slip just under the scrap's torn bottom edge, inside its shadow,
   holding /signin/'s own steps. The fields and buttons are site.css's; this
   only sets the paper and the handwritten note on it. */

.sl-join { position: relative; z-index: 2; margin-top: -16px; }
.sl-slip {
  position: relative;
  padding: var(--tud-space-5);
  border-radius: 4px;
  background:
    linear-gradient(var(--sl-wash), var(--sl-wash)),
    url('/assets/img/soon/paper-grain.webp') center / cover no-repeat,
    var(--sl-paper);
  background-blend-mode: normal, multiply, normal;
  box-shadow: 0 1px 2px rgba(20, 20, 18, 0.08), 0 18px 32px -16px var(--sl-shadow);
  transform: rotate(0.7deg);
}
.sl-join-note {
  /* One line's room whichever words the account check puts here. */
  height: 32px;
  margin-bottom: var(--tud-space-3) !important;
  font-family: var(--sl-hand);
  /* Down to 24px on the narrowest phones so the line stays on the paper. */
  font-size: clamp(24px, 8vw, 30px);
  font-weight: 700;
  line-height: 32px;
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--sl-note);
  transform: rotate(-1.5deg);
  transform-origin: left center;
}
.sl-form .field input { background: var(--tud-color-bg-surface); }
.sl-join-btn { position: relative; width: 100%; font-size: 17px; }
.sl-step-title { font-size: 21px; font-weight: 800; line-height: 1.2; letter-spacing: -0.02em; }
.sl-step-body { margin-top: var(--tud-space-2) !important; color: var(--tud-color-text-secondary); font-size: 15px; line-height: 1.5; }
.sl-step-body .si-path { color: var(--tud-color-text-primary); overflow-wrap: anywhere; }
.join-step { position: relative; }
.join-step > .sl-form { margin-top: var(--tud-space-4); }
.join-step > .sl-step-body + .btn { margin-top: var(--tud-space-5); }
.sl-form > .btn { margin-top: var(--tud-space-4); }
.sl-form > .fine { margin-top: var(--tud-space-3) !important; }
.sl-form > .form-msg { margin-top: var(--tud-space-2) !important; }
.sl-join .uni-pick-host { margin-top: var(--tud-space-2); }
/* A saved sign-in: the head script sets data-session="checking" before first
   paint, so a returning student sees "Checking your account..." rather than
   the email form flashing past; home-soon.js then opens the step the account
   is at (data-session="signed") or lifts the flag for the form. The line
   holds roughly the height of the step that replaces it. */
.sl-signed { display: none; }
[data-session="checking"] .sl-signed { display: block; min-height: 132px; }
[data-session="checking"] .sl-join-steps { display: none; }
[data-session="checking"] .tud-steps { visibility: hidden; }
/* Until the returning account's step has settled, the things below the step
   (the account line and, on a phone, the pass under the slip) wait unseen,
   so the step growing into place never shoves them about on screen. */
[data-session="checking"] :is(.sl-account, .sl-pass-wrap),
[data-settling] :is(.sl-account, .sl-pass-wrap) { visibility: hidden; }
.sl-signed-line { color: var(--tud-color-text-secondary); font-size: 16px; line-height: 1.5; }

/* Who is signed in, once someone is: one quiet line over the step, with the
   two things a student may want to fix. */
.sl-account {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 var(--tud-space-4);
  margin-top: var(--tud-space-5);
  padding-top: var(--tud-space-2);
  border-top: 2px dashed color-mix(in srgb, var(--tud-color-border-strong) 60%, transparent);
}
.sl-account-line { min-width: 0; color: var(--tud-color-text-muted); font-size: 14px; line-height: 1.4; overflow-wrap: anywhere; }
.sl-account-line strong { color: var(--tud-color-text-primary); font-weight: 700; }
.sl-account-links { display: flex; gap: var(--tud-space-4); }
.sl-account-links .link-button { min-height: 40px; font-size: 13px; }

/* The progress line sits between the handwritten note and the step. */
.sl-slip .tud-steps { margin-bottom: var(--tud-space-4); }
.sl-join .pv-title { font-size: 21px; }
/* .sl-home main p zeroes paragraph margins; the proof step's own spacing
   comes back here, matching the join steps' title-to-body rhythm. */
.sl-home .sl-join .pv-lede,
.sl-home .sl-join .pv-drop-hint { margin-top: var(--tud-space-2); }
.sl-home .sl-join .pv-note { margin-bottom: var(--tud-space-4); }
/* The code message sits between the boxes and the button, by the field. */
.sl-form > #join-code-msg:not(:empty) { margin-top: var(--tud-space-3) !important; }
.sl-form > #join-code-msg + .btn { margin-top: var(--tud-space-3); }
.sl-join .pv-lane .btn,
.sl-join .pv-actions .btn { font-size: 17px; }

/* ---------- the pass ----------
   The brand's real student pass, the one on the 2x5 ft standee and the
   ambassador posts, at web scale in HTML, CSS and SVG: a white card with the
   orange issuer band and the white wordmark, the punched slot with the ring
   through it, the logo mark as the emblem, Name and University fields, a
   status line where the rubber stamp lands once verification earns it, and
   the orange foot. From a tablet up it hangs on its printed lanyard. Its
   colours are its own, not the theme's: a white card stays white at night. */

/* No stacking context of its own here, so the card and its lanyard each
   take their place among the hero's layers: both under the scrap at rest,
   and the card alone lifted over everything while it is held. */
.sl-pass-wrap { position: relative; margin-top: clamp(28px, 6vw, 40px); }
.sl-pass-swing { position: relative; width: min(100%, 340px); margin-inline: auto; }
.sl-lanyard { display: none; }
/* home-soon.js turns the card toward a fine pointer (rotateX and rotateY on
   .sl-pass), slides the sheen with it and the shadow the other way, and sways
   .sl-pass-sway on the lanyard; each is transform and opacity only. */
.sl-pass-sway { position: relative; z-index: 0; }
.sl-pass-sway.is-held { z-index: 6; }
.sl-pass-shadow {
  position: absolute;
  z-index: -1;
  inset: 8% 5% -2%;
  border-radius: 26px;
  background: rgba(90, 24, 4, 0.55);
  filter: blur(22px);
  opacity: 0.32;
  transform: translateY(18px);
  pointer-events: none;
}
.sl-pass-sheen {
  position: absolute;
  z-index: 3;
  inset: -40%;
  background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0.2) 16%, rgba(255, 255, 255, 0) 36%);
  opacity: 0;
  pointer-events: none;
}
.sl-pass {
  position: relative;
  padding-bottom: 46px;
  border-radius: 26px;
  color: #141412;
  background: #FFFFFF;
  box-shadow: 0 1px 2px rgba(90, 24, 4, 0.14);
  overflow: hidden;
}
.sl-pass::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 22px; background: var(--sl-orange); }
.sl-pass-band { position: relative; padding: 32px 20px 14px; text-align: center; background: var(--sl-orange); }
/* The punched slot, and the split ring passing through it. The slot's top
   inner edge is in shadow so it reads as cut through the card. */
.sl-pass-slot {
  position: absolute;
  top: 11px;
  left: 50%;
  width: 62px;
  height: 14px;
  margin-left: -31px;
  border-radius: 7px;
  background: #C8410F;
  box-shadow: inset 0 2.5px 2.5px -0.5px rgba(0, 0, 0, 0.42), inset 0 -1px 0 rgba(255, 170, 130, 0.22);
}
.sl-pass-ring { position: absolute; top: 18px; left: 50%; display: block; width: 34px; height: 18px; margin-left: -17px; overflow: visible; }
.sl-pass-wordmark { display: block; width: 63%; height: auto; margin-inline: auto; }
.sl-pass-kind { display: block; margin-top: 10px; font-size: 17px; font-weight: 700; line-height: 1; color: #141412; }
.sl-pass-mark { display: block; width: 66px; height: auto; margin: 18px auto 0; }
.sl-pass-fields { display: grid; gap: 12px; margin: 16px 26px 0; }
.sl-pass-fields > div { display: grid; gap: 5px; }
.sl-pass-fields dt {
  font-family: var(--tud-font-secondary);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  color: #6B6660;
}
.sl-pass-fields dd { margin: 0; font-weight: 900; line-height: 1.02; letter-spacing: -0.02em; color: #141412; overflow-wrap: anywhere; }
.sl-pass-name { font-size: 32px; }
.sl-pass-uni { font-size: 19px; font-weight: 800; letter-spacing: -0.01em; }
/* Blank until the account fills them in. */
.sl-pass-fields dd[data-empty="true"] { color: #6B6660; }
/* The status block keeps its height whatever the account check writes into
   it after first paint, so nothing below moves. */
.sl-pass-status {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 72px;
  margin: 18px 22px 0;
}
.sl-pass-line {
  display: flex;
  align-items: center;
  min-height: 2.6em;
  max-width: 24ch;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  color: #55504A;
  text-wrap: balance;
}
/* The rubber stamp from the standee, only once it is earned. */
.sl-stamp { display: none; width: 90%; height: auto; overflow: visible; transform: rotate(-6deg); }
.sl-pass-status[data-state="done"] .sl-stamp { display: block; }
.sl-pass-status[data-state="done"] .sl-pass-line { min-height: 0; margin-top: 10px; font-size: 13px; color: #6B6660; }

/* ---------- the notebook sheet ----------
   Every line of text sits on a ruled line: the sheet runs on one 26px row, and
   every height inside it (type, links, gaps) is a whole number of rows. The
   rules are drawn 5px above each row's end, which puts them just under the
   Outfit baseline. */

/* The notebook and the two tickets share one wrapper that takes the hero's
   grid from a laptop up. */
.sl-lower { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 72px; margin-top: clamp(56px, 8vw, 88px); }
.sl-notebook { position: relative; }

.sl-sheet {
  --row: 26px;
  --sl-body: 15.5px;
  --sl-gap: 48px;
  --sl-pad-r: var(--tud-space-5);
  --sl-top: calc(var(--row) * 2);
  position: relative;
  padding: var(--sl-top) var(--sl-pad-r) var(--row) calc(var(--sl-gap) + 14px);
  border-radius: 3px;
  background:
    linear-gradient(to right, transparent var(--sl-gap), var(--sl-margin) var(--sl-gap), var(--sl-margin) calc(var(--sl-gap) + 1.5px), transparent calc(var(--sl-gap) + 1.5px)),
    repeating-linear-gradient(to bottom, transparent 0 calc(var(--row) - 1px), var(--sl-rule) calc(var(--row) - 1px) var(--row)) 0 calc(var(--sl-top) - 5px) / 100% calc(100% - var(--sl-top) - var(--row) + 5px) no-repeat,
    /* Crumpled paper from the collage kit (01-papers), multiplied into the
       sheet colour so the creases read in both themes. */
    linear-gradient(var(--sl-wash), var(--sl-wash)),
    url('/assets/img/soon/paper-grain.webp') center / cover no-repeat,
    var(--sl-paper);
  background-blend-mode: normal, normal, normal, multiply, normal;
  box-shadow: 0 1px 2px rgba(20, 20, 18, 0.08), 0 18px 32px -16px var(--sl-shadow);
  transform: rotate(0.5deg);
}
/* The punched holes along the top of a reporter's pad. */
.sl-sheet::before {
  content: "";
  position: absolute;
  top: 13px;
  left: 14px;
  right: 14px;
  height: 14px;
  background: radial-gradient(circle, var(--tud-color-bg-canvas) 5px, rgba(20, 20, 18, 0.14) 5.5px, transparent 6.5px) 0 0 / 30px 14px repeat-x;
}

.sl-note {
  height: var(--row);
  font-family: var(--sl-hand);
  font-size: clamp(24px, 9.4vw - 6px, 36px);
  white-space: nowrap;
  font-weight: 700;
  line-height: var(--row);
  letter-spacing: 0;
  color: var(--sl-note);
  transform: rotate(-2deg) translateY(-3px);
  transform-origin: left center;
}

.sl-list { margin: var(--row) 0 0; padding: 0; list-style: none; }
.sl-item {
  position: relative;
  padding-block: calc(var(--row) / 2);
}
/* A dashed pencil line between items, drawn without taking any height. */
.sl-item + .sl-item::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: repeating-linear-gradient(to right, var(--tud-color-border-strong) 0 6px, transparent 6px 11px);
}

.sl-box {
  position: absolute;
  top: calc(var(--row) / 2 - 4px);
  left: calc((var(--sl-gap) + 14px) * -1 + (var(--sl-gap) - 30px) / 2);
  width: 30px;
  height: 30px;
  color: var(--tud-color-text-primary);
}
.sl-box svg { display: block; width: 100%; height: 100%; overflow: visible; }
.sl-box-line { stroke-width: 2.2; }
.sl-box-tick {
  stroke: var(--sl-orange);
  stroke-width: 3.6;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  /* A round cap still paints a dot at a zero-length dash, so the tick is also
     hidden until it is earned. */
  opacity: 0;
}
.sl-item[data-state="done"] .sl-box-tick { stroke-dashoffset: 0; opacity: 1; }
.sl-item[data-state="review"] .sl-box-line { stroke: var(--sl-orange); stroke-dasharray: 4 4; }

.sl-item h3 {
  font-size: 22px;
  font-weight: 800;
  line-height: var(--row);
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.sl-item-body > p:not(.sl-links):not(.sl-aside),
.sl-dates {
  max-width: 44ch;
  color: var(--tud-color-text-secondary);
  font-size: var(--sl-body);
  line-height: var(--row);
  text-wrap: pretty;
}
/* The reassurance, written in the margin by hand: one ruled row. */
.sl-aside {
  font-family: var(--sl-hand);
  font-size: calc(var(--sl-body) + 7px);
  font-weight: 700;
  line-height: var(--row);
  color: var(--sl-note);
  transform: rotate(-1.2deg);
  transform-origin: left center;
  text-wrap: balance;
}
/* The draw's three dates, one ruled row each, a pencil dash for a bullet. */
.sl-dates { margin: 0; padding: 0; list-style: none; }
.sl-dates li { position: relative; padding-left: 20px; }
.sl-dates li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--row) / 2 - 1px);
  width: 11px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--sl-orange);
  transform: rotate(-8deg);
}
.sl-dates strong { color: var(--tud-color-text-primary); font-weight: 800; }

.sl-links {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--tud-space-5);
  margin-top: 0;
}
.sl-links a {
  display: inline-flex;
  align-items: center;
  min-height: calc(var(--row) * 2);
  color: var(--site-accent-text);
  font-size: calc(var(--sl-body) + 1px);
  font-weight: 800;
  line-height: var(--row);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
}
.sl-links a.sl-link-quiet { color: var(--tud-color-text-secondary); font-weight: 600; text-decoration-thickness: 1px; }

/* ---------- other doors: two paper tickets ----------
   The whole ticket is the link. The paper is the slip's (crumple grain
   multiplied into the surface colour), with two punched notches and a
   perforation before the stub, where the doodle sits. The notches are a
   mask, which would cut a box-shadow off too, so the shadow is a filter on
   the link and the mask is on the paper inside it. */

.sl-doors { display: grid; gap: 28px; }
.sl-ticket {
  --stub: 92px;
  --tilt: -1deg;
  position: relative;
  display: block;
  color: var(--tud-color-text-primary);
  text-decoration: none;
  border-radius: 14px;
  filter: drop-shadow(0 1px 1px rgba(20, 20, 18, 0.1)) drop-shadow(0 10px 12px var(--sl-shadow));
  transform: rotate(var(--tilt));
}
.sl-ticket + .sl-ticket { --tilt: 0.8deg; }
/* A strip of the hero's washi tape holds each ticket to the page. */
.sl-ticket::before {
  content: "";
  position: absolute;
  z-index: 2;
  top: -11px;
  left: 22px;
  width: 70px;
  height: 26px;
  background: url('/assets/img/soon/tape-stripes.webp') center / 100% 100% no-repeat;
  transform: rotate(-7deg);
  pointer-events: none;
}
.sl-ticket + .sl-ticket::before { left: auto; right: calc(var(--stub) + 18px); transform: rotate(6deg); }
.sl-ticket-paper {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--stub);
  min-height: 132px;
  border-radius: 14px;
  background:
    linear-gradient(to bottom, var(--tud-color-border-strong) 55%, transparent 55%) calc(100% - var(--stub)) 0 / 1.5px 9px repeat-y,
    linear-gradient(var(--sl-wash), var(--sl-wash)),
    url('/assets/img/soon/paper-grain.webp') center / cover no-repeat,
    var(--sl-paper);
  background-blend-mode: normal, normal, multiply, normal;
  -webkit-mask:
    radial-gradient(circle at calc(100% - var(--stub)) 0, transparent 10px, #000 10.5px) top / 100% 51% no-repeat,
    radial-gradient(circle at calc(100% - var(--stub)) 100%, transparent 10px, #000 10.5px) bottom / 100% 51% no-repeat;
  mask:
    radial-gradient(circle at calc(100% - var(--stub)) 0, transparent 10px, #000 10.5px) top / 100% 51% no-repeat,
    radial-gradient(circle at calc(100% - var(--stub)) 100%, transparent 10px, #000 10.5px) bottom / 100% 51% no-repeat;
}
.sl-ticket-main {
  display: grid;
  align-content: center;
  gap: 6px;
  padding: 22px 18px 20px 22px;
}
.sl-ticket-title { font-size: 20px; font-weight: 800; line-height: 1.15; letter-spacing: -0.015em; text-wrap: balance; }
.sl-ticket-text { max-width: 36ch; color: var(--tud-color-text-secondary); font-size: 15px; line-height: 1.45; text-wrap: pretty; }
.sl-ticket-go {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  color: var(--site-accent-text);
  font-size: 16px;
  font-weight: 800;
}
.sl-ticket-go svg { flex: 0 0 auto; }
.sl-ticket-stub { position: relative; }
.sl-ticket:hover .sl-ticket-go { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.22em; }
.sl-ticket:focus-visible { outline: 3px solid var(--tud-color-border-focus); outline-offset: 4px; }

/* ---------- the doodles ----------
   The brand's ink doodle set (theunideals-reel-kit/doodles-ink and
   doodles-orange) and the collage kit's peeking student, cropped to their ink
   and saved as WebP at twice the size they show. Ink on the light canvas,
   orange on the dark one (.theme-art in site.css). Each sits absolutely in a
   box that is already there, so none of them moves anything, and each is
   placed in a margin or a corner, never on a line of text. */

.sl-dd { position: absolute; z-index: 1; display: block; pointer-events: none; }
.sl-dd img { display: block; width: 100%; height: auto; }

/* The paper plane in the slip's top corner, only once a document is on its
   way to the team: one doodle, beside the short note, never by a heading. */
.sl-dd--plane { top: -18px; right: -6px; width: 74px; transform: rotate(-8deg); display: none; }
.sl-slip[data-stage="pending"] .sl-dd--plane { display: block; }
/* A chai glass put down on the notebook's corner. */
.sl-dd--chai { top: -36px; right: 14px; z-index: 2; width: 38px; transform: rotate(7deg); }
/* Two friends high-fiving, stuck over the sheet's bottom corner, under the
   draw line's links and clear of them. */
.sl-dd--friends { right: calc(var(--sl-pad-r) * -1 - 14px); bottom: calc(var(--row) * -1 - 46px); width: 104px; transform: rotate(-5deg); }
/* On the tickets' stubs: the shopfront for brands, the waving student for
   campus ambassadors. */
.sl-dd--shop { top: 50%; left: 50%; width: 70px; margin: -31px 0 0 -35px; transform: rotate(-3deg); }
.sl-dd--wave { top: 50%; left: 50%; width: 46px; margin: -43px 0 0 -23px; transform: rotate(3deg); }

/* ---------- the one moment ----------
   The scrap is slapped onto the page and settles on its tilt, the tape
   presses it flat just after, the megaphone gives one short buzz, and the
   pass badge stamps on last. Transform and opacity only, every element
   already in its place, so nothing shifts and first paint is final. Once it
   is over nothing moves unless the student does something: the ticks draw
   when verification earns them. All of it is off under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .sl-scrap-wrap { animation: sl-slap 900ms cubic-bezier(0.16, 1, 0.3, 1) both; }
  .sl-tape { animation: sl-tape 700ms cubic-bezier(0.16, 1, 0.3, 1) 380ms both; }
  /* The megaphone buzzes for half a second every six, the first time once the
     scrap has landed, and its three dashes shoot out from the bell with each
     buzz, the one ahead first. Both pause while the tab is hidden
     (home-soon.js sets data-hidden). */
  .sl-megaphone { animation: sl-buzz 6s ease-in-out 1000ms infinite; }
  .sl-burst-line { opacity: 0; animation: sl-burst 6s ease-out 1060ms infinite; }
  .sl-burst g:nth-child(2) .sl-burst-line { animation-delay: 1000ms; }
  .sl-burst g:nth-child(3) .sl-burst-line { animation-delay: 1120ms; }
  [data-hidden] .sl-megaphone,
  [data-hidden] .sl-burst-line { animation-play-state: paused; }
  /* The stamp lands when verification earns it, and the notebook tick draws. */
  .sl-pass-status[data-state="done"] .sl-stamp { animation: sl-stamp 520ms cubic-bezier(0.16, 1, 0.3, 1) both; }
  .sl-item[data-state="done"] .sl-box-tick { transition: stroke-dashoffset 420ms cubic-bezier(0.16, 1, 0.3, 1) 120ms; }
  /* A ticket straightens and lifts a little under the pointer. */
  .sl-ticket { transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1); }
  .sl-ticket-go svg { transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1); }
  .sl-ticket:hover { transform: rotate(0deg) translateY(-3px); }
  .sl-ticket:hover .sl-ticket-go svg { transform: translateX(3px); }
  /* A tap on a touch screen gives the card a small wobble. */
  .sl-pass.is-wobbling { animation: sl-wobble 700ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
  /* Where the lanyard shows, the pass swings once from the top of its straps. */
  @media (min-width: 720px) {
    .sl-pass-swing { animation: sl-swing 1900ms cubic-bezier(0.2, 0.7, 0.2, 1) 240ms backwards; }
    /* backwards, not both: once it has swung it keeps no transform, which
       would wall the card and its lanyard into one layer. */
    /* The card can be picked up off its lanyard (home-soon.js). The page
       still scrolls from everywhere else; on the card a touch drags it. */
    .sl-pass { cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none; }
    .sl-pass.is-dragging { cursor: grabbing; }
    .sl-pass img { -webkit-user-drag: none; }
  }
}
/* Each dash leaves the mouth, travels out along its ray and fades. The px
   here are the cut-out's own units, so the travel scales with it. */
@keyframes sl-burst {
  0% { opacity: 0; transform: translateX(-8px) scale(0.7); }
  2% { opacity: 1; transform: translateX(0) scale(0.85); }
  9% { opacity: 0; transform: translateX(22px) scale(1.15); }
  100% { opacity: 0; transform: translateX(22px) scale(1.15); }
}
@keyframes sl-wobble {
  0% { transform: rotate(0deg); }
  25% { transform: rotate(-1.8deg); }
  55% { transform: rotate(1.3deg); }
  80% { transform: rotate(-0.5deg); }
  100% { transform: rotate(0deg); }
}
/* --sl-swing scales the swing to the room beside the card: the page clips
   at its sides, and on a narrow tablet the card hangs close to the edge. */
@keyframes sl-swing {
  0% { transform: rotate(calc(-2.6deg * var(--sl-swing, 1))); }
  42% { transform: rotate(calc(1.6deg * var(--sl-swing, 1))); }
  74% { transform: rotate(calc(-0.6deg * var(--sl-swing, 1))); }
  100% { transform: rotate(0deg); }
}
@keyframes sl-slap {
  0% { transform: rotate(calc(var(--sl-tilt) - 3deg)) translateY(-14px) scale(1.035); }
  55% { transform: rotate(calc(var(--sl-tilt) + 0.7deg)) translateY(0) scale(0.998); }
  78% { transform: rotate(calc(var(--sl-tilt) - 0.4deg)) translateY(0) scale(1); }
  100% { transform: rotate(var(--sl-tilt)) translateY(0) scale(1); }
}
@keyframes sl-tape {
  0% { transform: rotate(-11deg) translateY(-8px) scale(1.06); }
  60% { transform: rotate(-3.9deg) translateY(0) scale(1); }
  100% { transform: rotate(-5deg) translateY(0) scale(1); }
}
/* Half a second of buzz at the start of each six-second cycle, then quiet. */
@keyframes sl-buzz {
  0%, 9%, 100% { transform: rotate(11deg) translate(0, 0); }
  1.1% { transform: rotate(9deg) translate(-1px, 1px); }
  2.2% { transform: rotate(13deg) translate(1px, -1px); }
  3.4% { transform: rotate(9.5deg) translate(-1px, 0); }
  4.5% { transform: rotate(12.5deg) translate(1px, 1px); }
  5.6% { transform: rotate(10deg) translate(0, 0); }
  6.7% { transform: rotate(11.8deg) translate(0, 0); }
  7.8% { transform: rotate(10.7deg) translate(0, 0); }
}
@keyframes sl-stamp {
  0% { opacity: 0; transform: scale(1.8); }
  70% { opacity: 1; transform: scale(0.94); }
  100% { opacity: 1; transform: scale(1); }
}

/* ---------- wider screens ---------- */

/* From a tablet up the scrap spans the page, the slip takes the left under
   it and the pass the right, which keeps the button on the first screen. */
@media (min-width: 720px) {
  .sl-hero {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "scrap scrap"
      "join pass";
    column-gap: clamp(32px, 5vw, 80px);
  }
  .sl-scrap-wrap { grid-area: scrap; margin-inline: 0; }
  .sl-megaphone { top: -64px; right: 56px; }
  .sl-join { grid-area: join; align-self: start; max-width: 480px; margin-top: -4px; }
  .sl-slip { padding: var(--tud-space-6); transform: rotate(-0.6deg); }
  .sl-join-note { font-size: 32px; }
  .sl-dd--plane { top: -26px; right: -10px; width: 92px; }
  /* The card's top lines up with the slip's, both just under the scrap. */
  .sl-pass-wrap { grid-area: pass; align-self: start; width: 100%; margin-top: -4px; }
  .sl-pass-swing { --sl-swing: 0.06; width: min(100%, 328px); transform-origin: 50% -230px; }
  .sl-pass-sway { transform-origin: 50% -230px; }
  /* The lanyard runs up from the slot and out of sight behind the scrap, so
     the card hangs from the page. The box is only as tall as the scrap can
     hide (the straps are sliced at its top edge), shorter on a tablet where
     the scrap is shorter too. */
  .sl-lanyard {
    display: block;
    position: absolute;
    z-index: 0;
    left: 50%;
    bottom: calc(100% - 16px);
    width: 220px;
    height: 170px;
    margin-left: -110px;
    /* Sliced only along the top, where the scrap hides the cut: the straps
       run on past the slot under the card, and while the card is dragged
       they turn out past the box's sides and bottom. */
    overflow: visible;
    clip-path: inset(0 -480px -640px -480px);
    pointer-events: none;
    filter: drop-shadow(-3px 4px 4px rgba(138, 37, 0, 0.3));
  }
  .sl-sheet { --sl-gap: 64px; --sl-pad-r: var(--tud-space-8); }
  .sl-dd--chai { top: -48px; right: 24px; width: 50px; }
  .sl-dd--friends { width: 128px; bottom: calc(var(--row) * -1 - 54px); }
  .sl-doors { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 32px; }
}

/* The load swing gets the room the card has to the page's clipped edge. */
@media (min-width: 768px) { .sl-pass-swing { --sl-swing: 0.35; } }
@media (min-width: 840px) { .sl-pass-swing { --sl-swing: 0.7; } }
@media (min-width: 960px) { .sl-pass-swing { --sl-swing: 1; } }

@media (min-width: 960px) {
  .sl-main { padding-top: clamp(40px, 5vw, 64px); }
  .sl-scrap { padding-inline: clamp(48px, 5vw, 72px); }
  /* The hero's two columns again: the sheet under the slip, the tickets
     under the pass, on the pass's centre line. */
  .sl-lower {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: clamp(32px, 5vw, 80px);
    align-items: center;
  }
  .sl-sheet { --row: 28px; --sl-body: 17px; }
  .sl-doors { grid-template-columns: minmax(0, 1fr); gap: 40px; width: min(100%, 460px); margin-inline: auto; }
  .sl-ticket { --stub: 112px; }
  .sl-ticket:first-child { margin-left: -16px; }
  .sl-ticket + .sl-ticket { margin-right: -16px; }
  .sl-ticket-paper { min-height: 150px; }
  .sl-ticket-main { padding: 26px 22px 24px 28px; }
  .sl-ticket-title { font-size: 22px; }
  .sl-ticket-text { font-size: 16px; }
  .sl-dd--shop { width: 84px; margin: -37px 0 0 -42px; }
  .sl-dd--wave { width: 54px; margin: -51px 0 0 -27px; }
  .sl-lanyard { height: 260px; }
}

.sl-applink { margin: var(--tud-space-3) 0 0; font-size: 14px; line-height: 1.4; }
.sl-applink a { margin: 0 2px; color: var(--tud-color-text-primary); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; min-height: 40px; display: inline-flex; align-items: center; }

/* ---------- the footer: the shared one ----------
   The markup is the shared footer (lib/site-chrome.js, written here by
   tools/site-chrome.mjs); this makes it read the same as /about/ and every
   other page, whose footers sit on site-launch.css and company-theme.css.
   Scoped to .footer so nothing else on the page moves. */
.sl-home .footer-column h2,
.sl-home .footer-social h2 { color: var(--tud-color-text-primary); }
/* Dark: the shared footer's warm palette, set as the tokens the footer reads. */
[data-theme="dark"] .sl-home .footer {
  --tud-color-bg-canvas: #1A1613;
  --tud-color-text-primary: #F6EFE4;
  --tud-color-text-secondary: #CBBFB0;
  --tud-color-text-muted: #B3A696;
  --tud-color-border-default: #352E27;
  --site-accent-text: #FF8A5C;
}
[data-theme="dark"] .sl-home .footer-company a { color: #CBBFB0; }
[data-theme="dark"] .sl-home .footer-landmark-image {
  filter: none;
  object-position: -99999px 0;
  background-image: url('/assets/footer-svg/footer-landmark-1080-dark.webp');
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: 100% 100%;
}
@media (min-width: 760px) {
  [data-theme="dark"] .sl-home .footer-landmark-image { background-image: url('/assets/footer-svg/footer-landmark-dark.svg'); }
}
