/* Define grayscale colors as CSS variables */
:root {
  --gray-50: #F8FAFC; /* Lightest gray */
  --gray-100: #F1F5F9; /* Lightest gray */
  --gray-200: #E2E8F0; /* Light gray */
  --gray-300: #CBD5E1; /* Medium gray */
  --gray-400: #94A3B8; /* Dark gray */
  --gray-600: #475569; /* Even darker gray */
  --gray-700: #334155; /* Very dark gray */
  --gray-800: #1E293B; /* Almost black */
  --gray-900: #0F172A; /* Black */
  --blue-400: #60A5FA; 
}

html { overflow-x: clip; } /* pair with body's clip so off-canvas items never scroll the page sideways */

body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center; /* Center horizontally */
  align-items: flex-start;
  overflow-x: clip; /* items can bleed past the edge without adding horizontal scroll */
}

.container {
  /* The page's real measure. Every below-hero band is --content wide and
     centred, which reproduces the old per-element `left:` gutters exactly:
     (1440 - 1328) / 2 = 56. Overridden per breakpoint in styles1440/1280. */
  --content: 1328px;
  --band-gap: 48px; /* the gutter between the two work columns */

  width: 1440px;
  position: relative;
  justify-content: center; /* Center horizontally */
  display: flex;
  flex-direction: column;
  /* Clears the FIXED actions bar (~91px tall from the viewport bottom) so it
     never covers the credits. This used to be slack baked into body's height.
     174px is measured: the old body height was 3281 and the credits ended at
     3107. */
  padding-bottom: 174px;
}

/* ── The below-hero flow layout ───────────────────────────────────────────────
   Everything below .hero used to be absolutely positioned canvas coordinates,
   carried by .draggable. The class is gone from that markup (hero-only
   interactivity), so real flow has to reproduce the same composition. */

/* Source order is About-first (SEO); visual order is Work-first. Absolute
   coordinates used to reconcile that on desktop and `order` did it on mobile.
   Now one block does both: .divider is display:none below 1025, so these six
   values produce the right desktop sequence AND the right stacked order. */
.container > .hero       { order: 0; }
.container > .divider    { order: 1; }
.container > .work-band  { order: 2; }
.container > .about-band { order: 3; }
.container > .collab     { order: 4; }
.container > .credits    { order: 5; }

/* Everything from here to the end of this block is DESKTOP CANVAS GEOMETRY,
   so it is scoped to >=1025. Below that the page is the plain stacked column it
   has always been: .container is 100% wide with `gap: 24px`, and each child
   carries its own side margin. That is exactly the contract
   `.draggable { position: static; width: auto }` used to enforce for these
   elements, and it stops working the moment the class comes off them — so a
   fixed measure, auto side margins, section margins, a two-column grid and an
   absolutely placed walk figure must all be absent there, not overridden. One
   media query does that with no mobile counter-rules to keep in sync. */
@media screen and (min-width: 1025px) {

  /* One measure for every band. Auto margins centre it in the 1440 container,
     which is what recreates the old 56px text edge without each element
     carrying its own `left:`. */
  .container > .divider,
  .container > .work-band,
  .container > .about-band,
  .container > .collab,
  .container > .credits {
    width: var(--content);
    margin-left: auto;
    margin-right: auto;
  }

  /* Vertical rhythm. Every value here is MEASURED from the rendered page at
     1600, not taken from the old CSS comments — those describe intent from an
     earlier state of the code and disagree with what actually renders. */
  .container > .divider    { margin-top: 5px; }  /* hero ends 900, divider at 905 */
  .container > .work-band  { margin-top: 61px; } /* divider ends 934, Work title at 995 */
  .container > .about-band { margin-top: 40px; } /* work rows end 1357, About title at 1397 */
  .container > .collab     { margin-top: 57px; } /* post-it box ends 2493, collab at 2550 */
  .container > .credits    { margin-top: 27px; } /* collab ends 3064, credits at 3091 */

  /* Two equal columns. The old coordinates tiled their container exactly
     (56 + 640 + 48 + 640 + 56 = 1440), so 1fr 1fr reproduces them to the pixel;
     only the gap differs per breakpoint. Row 1 is the two headings, row 2 the
     two frames, which is already their DOM order. */
  .work-band {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--band-gap);
    row-gap: 0; /* measured: titles occupy 995-1051 and the frames start at 1051 */
    /* start, not the default stretch: the two frames are different heights (220
       vs 306), and a stretched .projects-frame would centre its rows inside the
       taller row and drop them ~43px. */
    align-items: start;
  }
  /* .work-title also carries .projects-title, so its rule has to come second —
     equal specificity, later wins. justify-self:start keeps both headings
     shrink-wrapped, which is the width they had from .draggable's fit-content. */
  /* Work on the LEFT, Personal Projects on the right. The DOM is in that order
     too, so the mobile stack and the plain-text edition lead with Work without
     needing an `order:` or a data-md hoist to say so.
     Note .work-title's element carries BOTH classes (`projects-title
     work-title`), so these two rules tie on specificity and source order picks
     the winner: .work-title must stay LAST or the Work heading lands in the
     Projects column. */
  .work-band > .projects-title { grid-column: 2; grid-row: 1; justify-self: start; }
  .work-band > .work-title     { grid-column: 1; grid-row: 1; justify-self: start; }
  .work-band > .projects-frame { grid-column: 2; grid-row: 2; }
  .work-band > .client-frame   { grid-column: 1; grid-row: 2; }

  /* position:relative so the walk figure anchors to this band rather than to a
     3281px-tall container, which is what lets it float beside the paragraph
     without a hardcoded top. flex-start, not the default stretch: .about-title
     was fit-content via .draggable and would otherwise span the whole measure. */
  .about-band {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
  }
  .about-band > .about-title { margin-bottom: 39px; }  /* title ends 1453, lead at 1492 */
  .about-band > .about-lead  { margin-bottom: 127px; } /* lead ends 1850, timeline at 1977 */
  .about-band > .timeline    { margin-bottom: 119px; } /* timeline ends 2062, post-it BOX at 2181 */

  /* Scoped to the band, not bare `.walk-figure`, deliberately. The canvas-era
     `top:`/`right:` this originally defended against are gone from
     styles1440.css, but styles1280.css still overrides `right` here on purpose
     (the one width where the figure overhangs its band) and it loads LATER, so
     both rules have to stay at matching (0,2,0) for source order to decide the
     tie. Do not drop the scoping on one side without the other.
     144 is not the old 200: that measured from .container, this measures from
     .about-band, which is inset 56 at both 1440 and the base width. */
  .about-band > .walk-figure {
    position: absolute;
    right: 144px;
    /* Aligns the figure's VISIBLE top edge with the CAP TOP of the "About me"
       title, i.e. the top of the A, not the top of its line box.

       Two measured offsets, neither of them guessable:
       - walk.svg's artwork starts 111.9 units into its 1586-unit viewBox (7.06%
         of the height, via getBBox), which at the 415.68px render height leaves
         29.33px of transparent padding above the drawing. So the figure's box
         top and its visible top are not the same thing.
       - the title's cap top sits 8.25px into its own box: 0.5px half-leading
         (42px box, 36px font) + 33px ascent - 25.25px cap height, the last one
         read off a supersampled canvas render rather than estimated.

       8.25 - 29.33 = -21.08, and it is NEGATIVE because the title is the band's
       first child, so its box top IS the band's origin and anything aligning to
       the glyphs inside it has to start above that. The figure overflows the
       band upward by 21px; nothing clips it and .about-lead is narrowed at both
       desktop widths so there is no collision.

       One value covers both desktop bands: the figure is 260px wide at every
       width so the 29.33 holds, and .about-title is 36px in styles1280.css AND
       styles1440.css so the 8.25 holds. Re-derive if either changes. Below 1025
       the figure is in flow and `top` does nothing. */
    top: -21.08px;
    width: 260px;
  }

}

p {
  margin: 0px;
}

/* The floating actions bar: everything you can DO on this page, in one place.
   Holds the contact links (CV / E-mail / LinkedIn) and the canvas reset. The
   links used to sit absolutely positioned in the hero; moving them here frees
   the hero's top band for the name and the bio. */
.toolbar-container {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  width: fit-content;
  height: fit-content;
  display: flex;
  align-items: center;
  gap: 16px;
  z-index: 9999;
}

/* Style for the reset button */
/* doodle "sticker" button: outlined on the page background */
.reset-button {
  font-size: 12px;
  width: 4.4em;
  height: 4.4em;
  background: var(--gray-900);
  border: 3.5px solid #ffffff;
  border-radius: 45% 55% 45% 55% / 55% 45% 55% 45%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 5px 5px 0px #ffffff, 0 10px 24px rgba(0, 0, 0, 0.6);
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s ease, border-color 0.2s ease;
}

.reset-button:hover {
  transform: scale(1.05) rotate(-3deg);
  border-color: #83c6f9;
  box-shadow: 7px 7px 0px #83c6f9, 0 14px 30px rgba(0, 0, 0, 0.6);
}

.reset-button:active {
  transform: scale(0.95);
  box-shadow: 2px 2px 0px #ffffff, 0 5px 14px rgba(0, 0, 0, 0.55);
}

.reset-button svg {
  width: 2.6em;
  height: 2.6em;
  transform-origin: center;
}

/* one full turn on click (class toggled in script.js) */
@keyframes reset-spin {
  to { transform: rotate(360deg); }
}

.reset-button svg.spin {
  animation: reset-spin 0.5s ease;
}

/* Deliberately bare, not `.hero .draggable`, even though paper.css scopes its
   twin rule that way. Scoping this one too would raise it from (0,1,0) to
   (0,2,0) and risk the exact tie-break that unpinned the mobile avatar earlier
   in this refactor (see the specificity note in .draggable's ≤1024 block
   below). The hero-only boundary is enforced by markup (the class only ever
   appears inside .hero) plus canvas.test.js, not by this selector's shape. */
.draggable {
  width: fit-content;
  height: fit-content;
  cursor: grab;
  position: absolute;
  /* Drag position lives in --x/--y (written by script.js) so transform is never
     owned by inline styles. The hover reaction (tilt + lift + shadow) rides on
     the independent `rotate:`/`translate:` properties + `filter:`, so it composes
     with the position transform instead of clobbering it. Never transition
     `transform` here: it would lag the cursor mid-drag. */
  transform: translate(var(--x, 0px), var(--y, 0px));
  /* transparent resting drop-shadow so the hover shadow can fade in smoothly
     (filter can't tween to/from `none`). ponytail: always-on filter = one
     compositing layer per draggable; drop it if it ever costs paint perf. */
  filter:
    drop-shadow(0 0 0 rgba(28, 25, 23, 0))
    drop-shadow(0 0 0 rgba(28, 25, 23, 0));
  transition:
    rotate 0.18s cubic-bezier(0.3, 0.8, 0.4, 1),
    translate 0.18s cubic-bezier(0.3, 0.8, 0.4, 1),
    filter 0.18s ease;
}

/* Hover tilt is opt-in, only for the paper-like TEXT annotations — the typed
   and handwritten bits cock a touch like loose paper. Everything else stays put
   on hover: garments (you place them precisely on the avatar), arrows, pin,
   divider, buttons, and the avatar itself. Post-it notes/cards aren't listed
   here — they run their own straighten on hover in paper.css. No lift, no shadow:
   elevation is a DRAG tell (the drop-shadow below appears only while dragging).
   drop-shadow (not box-shadow) follows the alpha channel, so transparent PNGs
   and inline SVGs cast their real silhouette while dragging, not a box. */
.hero-hello:hover,
.hero-description:hover,
.hero-note:hover {
  rotate: -1.5deg;
}
.draggable.dragging,
.draggable-flow.dragging {
  cursor: grabbing;
  filter:
    drop-shadow(0 3px 4px rgba(28, 25, 23, 0.18))
    drop-shadow(0 14px 20px rgba(28, 25, 23, 0.22));
}

/* ── Draggable, but still in the document ────────────────────────────────────
   `.draggable` above carries position:absolute, which is right for the hero
   (its children are placed on a canvas) and fatal anywhere else: giving it to a
   flow element drops it out of flow and pulls the rest of the page up.

   Dragging does not actually need absolute positioning. Position rides --x/--y
   composed into a transform, and a transform moves an element visually without
   affecting layout, so a normal flow element drags perfectly well and nothing
   around it reflows. That is what this class is: `.draggable` minus the
   positioning.

   position:relative earns its keep twice — it lets script.js's maxZIndex bump
   actually apply (z-index is ignored on static elements, so a grabbed divider
   would otherwise stay behind whatever it was dragged over), and it costs
   nothing visually with no offsets set. It is safe here only because the
   breakpoint files no longer declare any top/left for .divider; check that
   before giving this class to anything else. */
.draggable-flow {
  position: relative;
  cursor: grab;
  transform: translate(var(--x, 0px), var(--y, 0px));
  filter:
    drop-shadow(0 0 0 rgba(28, 25, 23, 0))
    drop-shadow(0 0 0 rgba(28, 25, 23, 0));
  transition: filter 0.18s ease;
}

/* reset choreography: elements fly home with a spring (script.js staggers via
   transition-delay); a mid-flight grab is interruptible (script.js reads the
   live matrix and removes this class) */
.draggable.settling,
.draggable-flow.settling {
  transition:
    transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1),
    scale 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* one-time onboarding wiggle on the hint note (~1.5s after load) */
@keyframes hint-wiggle {
  0%, 100% { rotate: 0deg; }
  30% { rotate: 2.4deg; }
  70% { rotate: -1.8deg; }
}
.hero-note.wiggle { animation: hint-wiggle 0.7s ease-in-out 2; }

/* the avatar notices accessories: nudges bigger when you grab one */
@keyframes avatar-hint {
  0% { scale: 1; }
  25% { scale: 1.05; }
  70% { scale: 1.05; }
  100% { scale: 1; }
}
.avatar.avatar-hint { animation: avatar-hint 0.5s ease-in-out; }

@media (prefers-reduced-motion: reduce) {
  .draggable,
  .draggable.settling,
  .draggable-flow,
  .draggable-flow.settling { transition: none; }
  .draggable:hover { rotate: 0deg; } /* keep the lift + shadow, drop the sudden cock */
  .hero-note.wiggle,
  .avatar.avatar-hint { animation: none; }
}

/* At ≤1024 the draggable class stays on elements (script.js only disables the
   interactable, since removing the class also removed position:absolute and
   collapsed the desktop layout after a resize). Neutralize .draggable's own
   declarations so the stacked flow layout holds. The selection chrome (corner
   handles, hover borders, incl. the .collab variant) is neutralized in
   styles1024.css, which loads after this file and so wins the cascade over the
   later-in-this-file :hover rules at equal specificity. */
@media screen and (max-width: 1024px) {
  .draggable {
    position: static;
    width: auto;
    height: auto;
    cursor: default;
  }
  /* no hover reaction on the stacked mobile flow: touch :hover sticks, and a
     rotate/translate on a flow element would shift the layout (notes handle
     their own mobile neutralization in paper.css) */
  .draggable:hover {
    rotate: 0deg;
    translate: none;
    filter: none;
  }
}

.editablesquare1 {
  opacity: 0;
  width: 10px;
  height: 10px;
  background-color: var(--blue-400);
  border: 2px solid var(--gray-50);
  position: absolute;
  right: var(--sq, -6px);
  top: var(--sq, -6px);
}

.editablesquare2 {
  opacity: 0;
  width: 10px;
  height: 10px;
  background-color: var(--blue-400);
  border: 2px solid var(--gray-50);
  position: absolute;
  left: var(--sq, -6px);
  bottom: var(--sq, -6px);
}

.draggable:hover .editablesquare2,
.draggable-flow:hover .editablesquare2 {
  opacity: 1;
}

.draggable:hover .editablesquare1,
.draggable-flow:hover .editablesquare1 {
  opacity: 1;
}

/* ── Unified selection rectangle ─────────────────────────────────────────────
   One ring for every draggable, drawn as an OUTLINE (not a border). Outline is
   painted outside the box, so it is never clipped by a note's clip-path/mask and
   never distorted by the element's box-sizing — the geometry is identical on
   every element. The corner squares (.editablesquare1/2) ride on top. This is the
   single source of the selection box; the old scattered per-element
   `:hover { border-color }` rules were removed in favour of it. */
.draggable:hover,
.draggable:focus-visible,
.draggable-flow:hover,
.draggable-flow:focus-visible {
  outline: 2px solid var(--blue-400);
  outline-offset: 2px;
}

/* Corner handles sit centered ON the outline line. --sq is the handle offset: the
   14px square (10px + 2px border each side) centers on a line by sitting half its
   width past it — for the +2px outset ring that's -10px. Every draggable, notes
   included, uses this same offset: nothing clips the notes, so the chrome rides the
   element and needs no inset special-case. Case-study cards don't set --sq →
   they keep the -6px default for their own edge ring. */
.draggable,
.draggable-flow { --sq: -10px; }

.hero {
  position: relative;
  justify-content: center;
  display: flex;
  width: 1440px;
  height: 900px;
  /* Where the hint sits, as the POINT its box centres on. This used to be four
     tokens describing the hand-drawn ring's box (x/y/w/h), because the words had
     to land inside an ellipse; with the ring gone there is no box to fit inside,
     only a position to hold, so the pair below is the midpoint the old four
     resolved to (91 + 215/2, 363 + 98/2). The hint shrink-wraps its text and
     pulls back by half its own size, so it stays centred here whatever the copy
     is. Overridden per band in the breakpoint files. */
  --hint-cx: 198.5px;
  --hint-cy: 412px;
}

/* The avatar layer is a real box coincident with .hero (it needs one: the
   sticker-outline `filter` in paper.css renders the whole subtree's alpha as
   one shape, and filter does nothing on display:contents). inset:0 with no
   border/padding means its padding box IS the hero's box, so the children's
   top/left values are unchanged even though the filter makes the layer their
   containing block. Being absolutely positioned also keeps it out of the
   hero's flex flow at <=1024, where a zero-height flex item would still cost
   a full gap. pointer-events:none keeps the full-hero box from swallowing
   hover/drag aimed at hero elements beneath it; the pieces opt back in. */
.avatar-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.avatar-layer > .draggable {
  pointer-events: auto;
}

.hero-hello {
  top: 103px;
  font-size: 90px;
  line-height: 108px;
  font-weight: 700;
  color: var(--gray-100);
  text-align: center;
  width: fit-content;
  height: fit-content;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
}

.hero-description {
  top: 259px;
  font-size: 18px;
  line-height: 27px;
  font-weight: 400;
  color: var(--gray-400);
  text-align: center;
  width: 720px;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
}

.hero-description-lead {
  margin-bottom: 0;
}

/* Second sentence of the hero lead. A block span rather than a <br> so the
   break can carry spacing; <br> takes no margin. */
.hero-description-tail {
  display: block;
  margin-top: 10px;
}

.hero-role {
  font-weight: 600;
  color: #fff;
}

/* Plain text on the paper, not a sticky note: no face, no edge, no lift.
   The box is the TEXT's box: it shrink-wraps one nowrap line, and `translate:
   -50% -50%` pulls it back by half its own size so it stays centred on
   --hint-cx / --hint-cy whatever the copy is. Sizing it to anything larger would
   draw the selection outline and the corner handles — which ride this element —
   around empty space, promising a bigger target than there is.
   It no longer sets pointer-events. That pair (none on the box, auto on the
   children) existed so the ring's empty interior fell through to the ring
   underneath; with the ring gone there is no interior, and the box IS the words.
   `translate` is safe to own here: the hover reaction on .hero-note writes only
   `rotate`, script.js never adds .reveal to it (that list is below-fold
   elements), and the ≤1024 `translate: none` rule lands on a note that is
   display:none there. The drag transform is untouched — it rides `transform`. */
.hero-note {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  box-sizing: border-box;
  top: var(--hint-cy);
  left: var(--hint-cx);
  width: fit-content;
  height: fit-content;
  translate: -50% -50%;
  font-weight: 400;
}

/* Lives in .toolbar-container now, so it is a plain flex row — no absolute
   positioning, no auto margins to centre it in the hero. */
.social-button-group {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 16px;
  width: fit-content;
}

.social-button {
  width: fit-content;
  height: fit-content;
  border-radius: 20px;
  font-size: 16px;
  line-height: 18px;
  font-weight: 400;
  border: none;
  padding: 8px 16px 8px 12px;
  background-color: var(--gray-800);
  color: var(--gray-100);
  cursor: pointer;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  font-family: var(--pp-body);
  text-decoration: none;
}

.social-button:hover {
  background-color: var(--gray-700);
}

.social-button:active {
  background-color: var(--gray-600);
}




/* Colour, underline and hover come from THE LINK in paper.css. Only the
   padding that keeps the swipe off the glyphs is gone with the swipe. */
.mint-link { padding: 2px; }

/* STICKER BOXES AFTER THE BORDER-FREE ASSET SWAP
   The old files carried their white sticker border inside the bitmap (~18% of
   the pixels), so a 400px box showed ~296x353 of actual avatar. The new files
   are cropped tight to the artwork, so the SAME box would render the drawing
   ~20-35% larger. Every box below was recomputed from the old file's artwork
   bounding box to put the drawing back at its old on-screen size, and each
   `top` moved so the artwork's top edge stays put.
   The new exports are not the old drawings minus a ring: their artwork has a
   slightly different aspect (avatar 0.77 vs 0.84). So one dimension is matched
   and the other follows the file's true ratio: HEIGHT for the avatar, because
   that is what anchors the face for the beard and hats; WIDTH for the hats,
   because that is what reads against the head. These were starting points for
   eye-tuning, not pixel identity. */
.avatar {
  max-width: 271px;
  max-height: 353px;
  top: 394px;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
}
/* No [data-theme="dark"] override: the dark export is drawn at the SAME pixel
   scale as light (head pixels at identical coordinates) and its 30px of extra
   headroom is trimmed at conversion time, so one box serves both themes. If a
   future dark export stops being aligned, fix the FILE, not this rule. */

.avatar img {
  width: 100%;
  height: 100%;
}

.beard {
  /* Dialled repeatedly (readings 209-211 wide across 1055-1332); the latest,
     209x134, is adopted for EVERY desktop band here in base. The dial emits a
     left + right:auto pin, but each reading sat within a few px of centre —
     the centring below is the same position expressed in a way that stays
     glued to the (also centred) avatar at every band width. */
  max-width: 209px;
  max-height: 134px;
  top: 537px;
  /* left:-8 (not 0) biases the centring window so the beard sits 4px left of
     true centre — the auto margins split the extra 8px equally. Still centred
     RELATIVE to the avatar at every band, unlike a hard pin would be. */
  left: -8px;
  right: 0;
  margin-left: auto;
  margin-right: auto;
}

.beard img {
  width: 100%;
  height: 100%;
}

/* The three hats sit in the gaps the other pieces leave, spread around the
   avatar rather than stacked in one corner, so each reads as its own thing to
   pick up. Placement is by eye against the live hero; the constraint is only
   that they clear the text column, the avatar's box and each other.
   .beanie takes the upper-right slot the glasses used to hold.

   ── HEIGHT is the constrained axis for all three, width follows ─────────────
   Each slot holds a day/night PAIR (see index.astro) and the two files do NOT
   share an aspect ratio: beanie 1.336 vs flat cap 1.667, baseball cap 1.605 vs
   fedora 1.701, cowboy 1.601 vs wizard 1.949. The imgs used to be
   `width:100%; height:100%`, which stretches whatever it is handed — fine when
   a slot held one file forever, and a guaranteed distortion the moment it holds
   two. They are `height:100%; width:auto` now, so neither variant can squash.

   Given that, the slot has to pin ONE dimension. It pins height, for a
   structural reason: at 1025-1280 the hero's 828px height is derived from the
   deepest hero child, and styles1280.css documents a hard ~773 floor that the
   wizard-hat slot sits against. Pinning width instead would let a taller
   variant (the cowboy hat is 1.601 against the wizard's 1.949 — much chunkier
   at equal width) push straight through that floor. Pinning height keeps every
   swap inside the same vertical band; the widths differ between day and night,
   which is honest, since the hats really are different shapes.

   ── ONE HEIGHT TOKEN PER HAT, not per slot ─────────────────────────────────
   A slot's two files are two different hats, not two crops of one, so "the same
   height" is a starting point rather than a rule: the flat cap wants to sit
   differently from the beanie even though they share a corner. Each of the six
   gets its own token, defined on .hero below, and the theme picks which one the
   slot reads. The values were dialled by eye against the live canvas; a
   dev-only slider panel in index.astro drove these same tokens while they were
   being set, and was removed once they were. Re-tune by editing here.

   The day values are the heights the current hats already rendered at, so
   nothing on the light canvas moved. */
.hero {
  --hat-beanie: 194px;        /* light: beanie */
  --hat-beanie-dark: 160px;   /* dark:  flat cap */
  --hat-cap: 153px;           /* light: baseball cap */
  --hat-cap-dark: 181px;      /* dark:  fedora */
  --hat-cowboy: 220px;        /* light: cowboy hat */
  --hat-wizard: 189px;        /* dark:  wizard hat */
}

.beanie {
  height: var(--hat-beanie);
  width: auto;
  top: 328px;
  right: 99px;
}

.beanie img {
  height: 100%;
  width: auto;
}

/* Wizard hat and cap swapped sides: the hat takes the cap's old left slot and
   the cap takes the hat's old right one.
   The `@media (min-width:1280px) { .wizard-hat { margin-top: -80px } }` rule
   that used to sit here is GONE, folded into `top`. It belonged to the old
   right-flank placement, and a second vertical offset makes the declared `top`
   disagree with where the hat actually renders, which would make the dial
   panel read 80px off from reality. One property owns the vertical position. */
.wizard-hat {
  height: var(--hat-cowboy);
  width: auto;
  top: 591px;
  left: 5px;
}

.wizard-hat img {
  height: 100%;
  width: auto;
}

.baseball-cap {
  height: var(--hat-cap);
  width: auto;
  top: 678px;
  right: 152px;
}

.baseball-cap img {
  height: 100%;
  width: auto;
}

/* After dark each slot reads its night hat's own token. */
[data-theme="dark"] .beanie { height: var(--hat-beanie-dark); }
[data-theme="dark"] .baseball-cap { height: var(--hat-cap-dark); }
[data-theme="dark"] .wizard-hat { height: var(--hat-wizard); }

.pin {
  max-width: 160px;
  max-height: 160px;
  top: 1225px;
  left: 300px;
  display: none;
}

.about-me {
  /* Its box sits 16px LEFT of the content column (the old canvas coordinate was
     left:40 while the column starts at 56), so it needs a negative margin inside
     .about-band, not alignment to the column edge. The 1.1deg tilt in paper.css
     inflates its bounding rect, so a rect measurement will not equal 880 + 64. */
  margin-left: -16px;
  display: flex;
  flex-direction: column;
  padding: 32px;
  min-width: 880px;
  width: 880px;
  /* paper.css paints this note on top; kept tracking --note-canary so the base
     layer never shows a mismatched sliver */
  background-color: var(--note-canary, #F0E7A4);
  box-shadow: -16px 16px 0px 0px rgba(0, 0, 0, 0.50);
}

/* Standalone stack below the post-it, not parented to the note. Three cards
   cycle 1→2→3 on a loop (see below). Images carry no chrome beyond a soft
   drop-shadow. */
.about-stack {
  width: 276px;  /* 1.5x the original 184px */
  height: 276px;
}
/* It flows inside .about-band now, but the three stacked <img>s below are
   inset:0 against it, so it still has to be a containing block.
   This was `.about-band > .about-stack { position: relative; inset: auto }`
   while styles1440.css and styles1280.css still carried `top:`/`left:` for this
   element from the canvas era. Those coordinates are deleted (both files now
   keep only width/height here), so there is nothing left to disarm and the
   scoping that outweighed them is no longer needed.
   If a breakpoint ever re-introduces a `top`/`left` for .about-stack, know that
   raising this rule's specificity is NOT enough by itself: specificity only
   settles conflicts between declarations of the SAME property, so a rule
   declaring `position` alone leaves the offsets nothing to lose to. The guard
   has to re-declare `inset: auto` too. Measured, not assumed: with position
   alone the computed top stayed 2198px and un-hiding the stack dropped it
   3325px below the About title. */
.about-stack { position: relative; }
/* ponytail: 3-layer stack animation hidden for now. It flows inside .about-band,
   so un-hiding it costs a row in that column rather than a canvas coordinate.
   Delete this one rule to bring it back. */
.about-stack { display: none; }
.about-stack img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 4px 7px rgba(28, 25, 23, 0.20));
  opacity: 0; /* driven by the loop */
  animation: about-stack-cycle 2.4s linear infinite backwards;
}
/* Three cards share ONE cycle, phase-shifted by a third (0.8s) so the top card
   cycles 1 → 2 → 3 → 1 → 2 → 3 … forever, each held ~0.8s. Each pops in on top
   (z-index 3), the keyframes step its z-index down (2, 1) as the next cards land
   over it, and at the bottom (covered) it silently loops back to the top and
   pops in again. nth-OF-TYPE (not nth-child), kept from when leading
   .editablesquare divs used to shift which image got which delay. */
.about-stack img:nth-of-type(1) { animation-delay: 0s; }
.about-stack img:nth-of-type(2) { animation-delay: 0.8s; }
.about-stack img:nth-of-type(3) { animation-delay: 1.6s; }

@keyframes about-stack-cycle {
  0%      { opacity: 0; scale: 0.85; z-index: 3; } /* lands on top, popping in */
  8%      { opacity: 1; scale: 1;    z-index: 3; } /* quick pop, then a long clear hold */
  33.333% { z-index: 3; }
  33.334% { z-index: 2; } /* next card just landed on top; drop a level */
  66.666% { z-index: 2; }
  66.667% { z-index: 1; } /* now at the bottom, fully covered */
  100%    { opacity: 1; scale: 1;    z-index: 1; } /* loops back to top next cycle */
}

@media (prefers-reduced-motion: reduce) {
  .about-stack img { animation: none; opacity: 1; scale: 1; }
}

/* Animated walking figure beside the About description. The <img> loads the SVG,
   whose internal CSS @keyframes play the walk cycle. Placement is in the flow
   layout block at the top of this file (absolute against .about-band). */
.walk-figure img { display: block; width: 100%; height: auto; }

.about-me-title {
  font-size: 28px;
  font-weight: 500;
  color: var(--gray-800);
  width: fit-content;
}

.about-me-text {
  display: none;
}

.about-me-tagline {
  display: none;
}

/* Hide the default checkbox */
.custom-checkbox input[type="checkbox"] {
  display: none;
}

.custom-checkbox {
  display: flex;
  align-items: flex-start; /* top-align checkbox with first line of wrapped text */
  margin-top: 24px;
  margin-left: 4px;
  cursor: pointer;
}

/* Style the custom checkbox container */
.custom-checkbox .checkbox-custom {
  min-height: 24px;
  height: 24px;
  min-width: 24px;
  width: 24px;
  cursor: pointer;
  position: relative;
  background-image: url(assets/checkbox-unchecked.svg);
  background-repeat: no-repeat;
}

.custom-checkbox input[type="checkbox"] + .checkbox-custom::before {
  content: "";
  width: 24px;
  height: 24px;
  background-image: url(assets/checkbox-checked.svg);
  border-radius: 50%; 
  position: absolute;
  top: 12px;
  left: 12px;
  transform: translate(-50%, -50%) scale(0); 
}

/* Style Checked State */
.custom-checkbox input[type="checkbox"]:checked + .checkbox-custom::before {
  transform: translate(-50%, -50%) scale(1); /* Show the checkmark */
}

.input-field {
  border: none;
  background: none;
  color: var(--gray-800); /* Match the color of checkbox label text */
  font-size: 16px; /* Match the font size of checkbox label text */
  font-weight: 400; /* Match the font weight of checkbox label text */
  outline: none; /* Remove input field outline on focus (optional) */
  width: 100%; /* Expand the input field to fill the container */
  margin-left: 8px;
  font-family: var(--pp-body);
  resize: none;
  height: fit-content;
}

/* The new-item input reads as inline text on the sticky, so suppress the global
   :focus-visible ring (paper.css) here — the text caret already signals focus.
   Higher specificity than paper's bare `:focus-visible`, so it wins the cascade. */
.input-field:focus,
.input-field:focus-visible {
  outline: none;
}

.input-field::placeholder {
  color: rgba(0, 0, 0, 0.5);
}

.custom-checkbox input[type="checkbox"]:checked + .checkbox-custom + .input-field {
  font-weight: 600; /* Make the label text bold */
  color: var(--gray-900);
}

/* Strike through the item text when checked (presets use .text-content, new items use .input-field) */
.custom-checkbox input[type="checkbox"]:checked ~ .input-field,
.custom-checkbox input[type="checkbox"]:checked ~ .text-content {
  text-decoration: line-through;
}

#addCheckbox {
  margin-top: 24px;
  width: fit-content;
  height: fit-content;
  border-radius: 20px;
  font-size: 16px;
  line-height: 18px;
  font-weight: 400;
  border: none;
  padding: 8px 16px 8px 12px;
  background-color: rgba(0, 0, 0, 0.1);
  color: rgba(0, 0, 0, 0.8);
  cursor: pointer;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  font-family: var(--pp-body);
}

#addCheckbox:hover {
  background-color: rgba(0, 0, 0, 0.2);
}

#addCheckbox:active {
  background-color: var(--gray-600);
}

.divider svg {
  width: 1328px;
  height: 24px;
}

/* ── About-me section: title → lead → timeline → post-it ──────────────────── */
.about-title {
  font-size: 43px;
  font-weight: 600;
  color: var(--gray-100);
}
.about-lead {
  width: 760px; /* a measure for the bio, not a layout width */
  display: flex;
  flex-direction: column;
  gap: 14px;
  font-size: 17px;
  line-height: 1.55;
  color: var(--pp-body-ink);
}
.about-lead p { margin: 0; }
/* inline emphasis in the bio: bold keywords + highlighter swipes (paper.css) for
   scannability */
.about-lead strong { font-weight: 600; color: var(--pp-ink); }

/* Career timeline — a horizontal band of roles on a hand-drawn baseline. It
   flows between the lead and the post-it (the gaps live on .about-band above);
   styles1024.css turns .timeline-track into a swipe strip on small screens. */
.timeline {
  width: var(--content); /* the full page measure, same as the bands */
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.timeline-track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  position: relative;
}
/* the pencil baseline the dots sit on */
.timeline-track::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 6px;
  right: 6px;
  height: 2px;
  background: var(--pp-accent);
  opacity: 0.45;
}
.timeline-item {
  position: relative;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 26px 20px 0 0;
}
.timeline-item::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--pp-accent);
  border: 2px solid var(--pp-paper);
  box-sizing: border-box;
}
.timeline-year {
  font-family: var(--pp-mono);
  font-size: 11px;
  color: var(--pp-accent-deep);
}
.timeline-role {
  font-family: var(--pp-display);
  font-weight: 700;
  font-size: 16px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--pp-ink);
}
.timeline-company {
  font-family: var(--pp-body);
  font-size: 13px;
  color: var(--pp-ink-soft);
}
.timeline-hint { display: none; } /* swipe affordance is mobile-only */

/* Preset items render as wrapping text (inputs can't wrap); "New" items keep their editable input */
.text-content {
  display: block;
  flex: 1;
  min-width: 0; /* allow the flex item to shrink so text wraps instead of overflowing */
  margin-left: 8px;
  color: var(--gray-800);
  font-size: 16px;
  font-weight: 400;
}

.custom-checkbox:not(.new-item) .input-field {
  display: none;
}

.projects-title {
  font-size: 43px;
  font-weight: 600;
  color: var(--gray-100);
}

/* Public projects and gated client work share one horizontal band, but never
   one container: the headings make ownership and access clear before a click.
   Which column each heading lands in is set by the .work-band grid above. */

.project {
  width: 100%;
  height: 400px;
}

.work-frame {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 16px;
  padding: 24px 0; /* vertical only — the ledger rules must line up with the "Work" heading */
  /* No `position` here on purpose. The .work-band grid supplies the width (one
     1fr column) and the placement, and STATIC is what keeps the `top:`/`left:`
     rules still sitting in styles1440.css / styles1280.css inert — a
     position:relative here turns every one of them back into a live offset and
     throws the frames off by their old canvas coordinate. The cost is that
     ::before below has no local containing block; it is display:none in
     paper.css, so nothing paints. .work-frame is deliberately position:static:
     the old breakpoint `top:`/`left:` coordinates that motivated this comment
     are gone now, so there is nothing left for a position:relative here to
     re-arm. If it is ever given a position again, confirm first that no
     breakpoint file has re-declared an offset for it. */
  border-radius: 24px;
  color: var(--gray-400);
  font-size: 18px;
  line-height: 25px;
}
/* top-lit gradient border ring: recreates the old work-frame border, scales to any size */
.work-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px; /* ring thickness */
  background:
    radial-gradient(120% 70% at 50% 0%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 60%),
    linear-gradient(180deg, #52637A 0%, rgba(49, 59, 73, 0) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

/* Work ledger: one ruled row per case study, so more items fit without the
   frame growing. Each row is name + one line + arrow; a hairline rule separates
   them (last row has none, the frame ends there). */
.work-list {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

.work-row {
  box-sizing: border-box;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 24px;
  padding: 20px 0;
  border-block-end: 1px solid var(--gray-700);
  text-decoration: none;
  text-align: left;
  cursor: pointer;
}
.work-item:last-child .work-row { border-block-end: 0; }

/* Rows are plain links, not cards: no surface and no selection chrome. Hover
   underlines the title the way any text link would, while the whole row stays
   the hit area. Keyboard focus still needs to be visible, so :focus-visible
   keeps a ring. */
.work-row:hover .row-title {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.work-row:focus-visible {
  outline: 2px solid var(--blue-400);
  outline-offset: 2px;
}

.row-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0; /* lets the 1fr column actually shrink instead of overflowing */
}
.row-title {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--gray-50);
}
.row-desc {
  font-size: 13px;
  line-height: 1.45;
  color: var(--gray-400);
  /* one line by design; the clamp is a safety net if copy is edited longer */
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.row-arrow {
  font-size: 18px;
  line-height: 1;
  color: var(--gray-400);
}

/* Password gate (sits in the .work-frame until unlocked) */
#gate { min-height: 300px; } /* matches the neighbouring Projects ledger */
/* Both of these beat .work-frame's display:flex, which ignores [hidden]. The
   #protected half matters more now than it did: the two frames share ONE
   .work-band grid cell, so a hidden-but-displayed #protected is a stray item
   sitting on top of the gate rather than a harmless empty box beside it. */
#gate[hidden],
#protected[hidden] { display: none; }
.gate-msg { margin: 0; color: var(--gray-300); font-size: 16px; }
.gate-form { display: flex; gap: 14px; align-items: stretch; } /* button stretches to the input's height */

/* doodle "sticker" treatment, matching .reset-button */
.gate-form input,
.gate-form button {
  font: inherit;
  background: var(--gray-900);
  border: 3.5px solid #fff;
  color: #fff;
  box-shadow: 5px 5px 0 #fff;
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s ease, border-color 0.2s ease;
}
.gate-form input {
  padding: 12px 16px;
  border-radius: 14px;
}
.gate-form input::placeholder { color: var(--gray-400); }
.gate-form input:focus {
  outline: none;
  border-color: #83c6f9;
  box-shadow: 7px 7px 0 #83c6f9;
}
.gate-form button {
  padding: 12px 22px;
  border-radius: 14px;
  font-weight: 700;
  cursor: pointer;
}
.gate-form button:hover {
  transform: scale(1.05) rotate(-3deg);
  border-color: #83c6f9;
  box-shadow: 7px 7px 0 #83c6f9;
}
.gate-form button:active {
  transform: scale(0.95);
  box-shadow: 2px 2px 0 #fff;
}
.gate-error { color: #f87171; font-size: 12px; }
.gate-tagline { margin: 4px 0 0; font-size: 12px; color: var(--gray-400); }
/* THE LINK (paper.css) owns colour and underline. */

/* Collaboration section (gated, sits below Work in the fragment) */
.collab {
  /* Left edge and width come from the shared band measure at the top of this
     file, the same one .divider, .work-band, .about-band and .credits use, so
     every section's first glyph lands on the page's text column. */
  color: var(--gray-300);
}
.collab-top { display: flex; gap: 64px; margin-bottom: 80px; }
.collab-intro { flex: 0 0 36%; }
.collab-title {
  margin: 0 0 40px;
  font-size: 43px;
  font-weight: 600;
  color: var(--gray-100);
}
.collab-statement { margin: 0; font-size: 27px; line-height: 1.32; font-weight: 400; color: var(--gray-100); }
.collab-quotes { flex: 1; display: grid; grid-template-columns: repeat(2, 1fr); gap: 44px 48px; align-items: start; }
.quote { min-width: 0; margin: 0; }
.quote-name { margin: 0; font-size: 14px; font-weight: 600; color: var(--gray-50); }
/* The two attribution lines sat flush (both margin:0, both line-height:normal),
   so the mono role crowded the name. 5px is deliberately a quarter of the 20px
   .quote-text carries below: enough air to separate the two lines, small enough
   that name + role still read as one attribution block rather than two. */
.quote-role { margin: 5px 0 0; font-size: 14px; font-weight: 600; color: var(--gray-50); }
.quote-text {
  /* the down-arrow that used to separate the attribution from the quote is
     gone; it carried the gap in its own 16px margins, so the text owns it now */
  margin: 20px 0 0;
  font-size: 13px;
  line-height: 1.65;
  color: var(--gray-300);
}
.quote-text mark { background: #83c6f9; color: var(--gray-900); padding: 0 2px; border-radius: 2px; }

/* box-sizing lives on .collab .quote in paper.css, alongside the padding it has
   to contain. Nothing here is draggable any more, so the old
   `.collab .draggable { position:relative; cursor:move }` rule is gone. */
.collab-contributions { display: flex; flex-wrap: wrap; gap: 40px; }
.collab-contributions[hidden] { display: none; } /* beats the flex above (same pattern as #gate[hidden]) */
.contribution { flex: 1 1 380px; min-width: 0; }
.contribution h3 { margin: 0 0 8px; font-size: 19px; font-weight: 600; color: var(--gray-50); line-height: 1.25; }
.contribution p { margin: 0 0 20px; font-size: 14px; line-height: 1.6; color: var(--gray-400); }
/* two framed shots per box, fanned: the second sits to the right and lower, overlapping the first */
.contribution-media { display: flex; align-items: flex-start; }
.contribution-media img { width: 60%; height: auto; flex: none; }
.contribution-media img:last-child { margin-left: -20%; margin-top: 4.5%; }

.credits {
  /* text edge comes from the shared band measure at the top of this file */
  color: var(--gray-400);
  font-size: 12px;
}

/* Colour, underline and hover come from THE LINK in paper.css. */
.credit-link { padding: 2px; font-weight: 500; }
/* Touch dress-up subset: ONLY on a coarse pointer at desktop width (>=1025px),
   where the canvas layout is shown and drag is enabled. There the .dressup
   pieces capture a touch-drag (touch-action:none) and show their corner handles
   at rest as a "grab me" affordance. Below 1025px drag is off entirely, so this
   must NOT apply — touch-action:none would block page scroll and the handles
   would paint desktop selection chrome on the stacked flow. */
@media (pointer: coarse) and (min-width: 1025px) {
  .dressup { touch-action: none; }
  .dressup .editablesquare1,
  .dressup .editablesquare2 { opacity: 0.65; }
}

/* Semantic pass: the name is an <h1> now — inherit the .hero-hello look so the
   UA h1 margin/size doesn't change anything visually. Same for the about-me
   title <p role=heading>. */
.hero-hello h1 { font: inherit; margin: 0; letter-spacing: inherit; color: inherit; }

/* Keyboard access (Phase 6): focus looks native to the design-tool metaphor —
   the selection handles + a red-pencil ring. .sr-only hides the live region. */
/* focus ring matches the hover outline (defined together above); the handles
   also show so keyboard users get the same selection affordance */
.draggable:focus-visible .editablesquare1,
.draggable:focus-visible .editablesquare2 { opacity: 1; }
.dressup.kb-grabbed { outline: 2px dashed var(--blue-400); outline-offset: 3px; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------------------
   TL;IAA — the plain-text edition control (link + copy + password popover).
   Structure and position; paper.css carries the skin.
--------------------------------------------------------------------------- */
.tliaa {
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  width: fit-content;
  min-height: 43px;
  z-index: 60;
}

.tliaa-link {
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-decoration: none;
}
.tliaa-mark {
  font-family: var(--pp-mono, monospace);
  font-size: 13px;
  letter-spacing: 0.04em;
}
.tliaa-expand { font-size: 9px; }

/* Size, fill and shadow all come from .btn in paper.css. Only the busy state
   belongs here; the agent-mode gate lives in paper.css, which loads after .btn
   and so can actually beat its display:inline-flex. */
.tliaa-copy[disabled] { cursor: progress; opacity: 0.6; }

/* Reserves no space when empty, so the control does not jump on first copy. */
.tliaa-status {
  font-size: 9px;
  max-width: 210px;
  line-height: 1.35;
  flex-basis: 100%;
}
.tliaa-status:empty { display: none; }

/* Top-layer popover: script.js sets left/top from the button's rect, so the
   default centring must be cleared. */
.tliaa-gate {
  position: fixed;
  margin: 0;
  inset: auto;
  width: 260px;
  padding: 14px;
  border: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tliaa-gate:not(:popover-open) { display: none; }
.tliaa-gate-msg { font-size: 10px; line-height: 1.4; }
.tliaa-gate-form { display: flex; gap: 6px; }
.tliaa-gate-form input { flex: 1; min-width: 0; font: inherit; font-size: 10px; padding: 5px 8px; }
.tliaa-gate-form button { font: inherit; font-size: 10px; cursor: pointer; padding: 5px 9px; white-space: nowrap; }
.tliaa-gate-error { font-size: 9px; }

/* Fixed top-left chrome, like the desk lamp: no drag handles and no movement
   when agent mode adds its copy action. */
.tliaa {
  position: absolute;
  top: 32px;
  left: 48px;
  right: auto;
  margin: 0;
}
