/* ============================================================================
   craft.css — layout, effect and motion layer for the Stylin landing page.

   Loaded AFTER redesign.css. It does not introduce a new visual identity:
   ground, Anton display type and the cobalt accent are inherited from
   redesign.css tokens. What it adds is the thing the site had none of —
   depth, kinetic type, scroll-driven motion and reactive elements.

   Rules this file follows:
   - Content is visible by default. Every entrance animation lives inside an
     @supports (animation-timeline: view()) block, so a browser without
     scroll-driven animation renders the page fully, statically, and correct.
     Nothing here can strand content behind JavaScript.
   - prefers-reduced-motion switches the whole layer off at the bottom.
   - No new colours. Everything resolves to --c-accent-500 / --c-neutral-*.
   ============================================================================ */

:root {
  --craft-ease: cubic-bezier(0.22, 1, 0.36, 1);   /* decelerate — entrances */
  --craft-ease-io: cubic-bezier(0.65, 0, 0.35, 1); /* both ends — state swaps */
  --craft-rule: 2px;
}

/* ---------------------------------------------------------------------------
   1. Kinetic masthead
   The h1 is split into per-word spans by motion.js. Each word rides up from
   behind a clipping mask, staggered, so the headline builds like a title
   sequence instead of appearing all at once. Text content is never altered.
   --------------------------------------------------------------------------- */

.craft-line {
  display: block;
  overflow: hidden;      /* the mask the words rise out of */
  padding-bottom: 0.04em; /* let descenders clear the mask edge */
}

.craft-word {
  display: inline-block;
  will-change: transform;
}

/* Hairline that draws itself across the hero once the masthead has landed. */
/* Explicit length: .walsh-left-hero is a flex column, so a display:block
   child collapses to zero width. A measured rule reads better here than a
   full-bleed one regardless. */
.walsh-left-hero .craft-rule {
  display: block;
  width: clamp(120px, 22vw, 260px);
  height: var(--craft-rule);
  background: var(--c-accent-500);
  transform-origin: left center;
  margin: 22px 0 26px;
}

/* ---------------------------------------------------------------------------
   2. Hero composition
   Desktop: the display type breaks the image's left edge, so the two columns
   interlock instead of sitting in separate boxes. The image gets a cobalt
   under-plate that offsets it off the flat background.
   --------------------------------------------------------------------------- */

/* Full-bleed hero on large screens.
   site.css:87 caps every .w-container at --max-width (1200px), so above that
   the hero sat as a 1200px column with dead ground either side — at 2000px
   that is 400px of black on each flank. Here the hero alone breaks out: type
   block keeps a generous left margin, image runs to the right viewport edge.
   Scoped to the hero band, so every other section keeps the site measure.

   The !important flags are unavoidable: stylinai.webflow.css:1876 places both
   hero columns with ID selectors (#w-node-…{grid-area:1/1/2/7}), which no
   class selector can outrank. */
@media (min-width: 1200px) {
  .walsh-background-darkgreen > .walsh-container.w-container {
    max-width: none;
    width: 100%;
    padding-left: clamp(40px, 6vw, 128px);
    padding-right: 0;
  }

  /* Left column is capped rather than proportional: the type block has its
     own 620px measure, so a fr-sized column just banks unusable slack
     between the text and the image. Everything past the cap goes to the
     image, which is what should grow on a wide screen. */
  .walsh-background-darkgreen .walsh-main-grid-no-gap {
    grid-template-columns: minmax(400px, 700px) minmax(0, 1fr);
    column-gap: clamp(40px, 4vw, 88px);
    align-items: stretch;
  }

  .walsh-background-darkgreen .walsh-left-hero {
    grid-area: auto !important;
    align-self: center !important;
    max-width: 620px;
  }

  .walsh-background-darkgreen .walsh-ui-image-wrapper {
    grid-area: auto !important;
    place-self: stretch !important;
    /* aspect-ratio would keep driving height from width once the column is
       this wide; let the row height lead instead. object-fit:cover on the
       frames means nothing distorts. */
    aspect-ratio: auto;
    max-height: none;
    min-height: min(86vh, 920px);
    border-radius: 6px 0 0 6px;
  }

  /* The plate moves to the inboard side: the image's right edge is now the
     viewport edge, so an outboard plate would be off-screen. */
  .walsh-background-darkgreen .walsh-ui-image-wrapper {
    box-shadow: -18px 0 0 0 var(--c-accent-500);
  }
}

@media (min-width: 992px) {
  .walsh-left-hero { position: relative; z-index: 2; }

  /* Offset cobalt plate behind the hero image. Drawn as a box-shadow, not a
     pseudo-element: .walsh-ui-image-wrapper is overflow:hidden (it clips the
     rotating frames), so any child plate would be clipped away. A shadow
     paints outside the border box and survives.

     Horizontal offset only. The image's bottom edge sits flush with the
     bottom of the dark hero band, so any positive Y offset spills the plate
     onto the light proof strip below it. */
  .walsh-ui-image-wrapper {
    box-shadow: 18px 0 0 0 var(--c-accent-500);
  }
}

/* Deliberately NOT animating transform on .hero-rota__img: redesign.css:1525
   documents that a scale tied to .is-active snaps back when a frame
   deactivates mid-zoom, reading as a zoom-out during the fade. The existing
   opacity cross-dissolve stands. */

/* Below 992px stylinai.webflow.css:1229 centres .walsh-left-hero, but
   .app-cta-cluster is a flex row left over from the desktop layout — its
   default justify-content:flex-start left-anchors the badge and the rating,
   and once the row wraps they stack against the left edge while the headline
   and paragraph above them are centred. Centre the cluster with them. */
@media (max-width: 991px) {
  .walsh-left-hero .app-cta-cluster {
    justify-content: center;
    text-align: center;
  }

  /* The rule is a fixed-width block, so it needs centring explicitly once the
     hero stacks — it does not inherit the centred text alignment. */
  .walsh-left-hero .craft-rule { margin-inline: auto; }

  .walsh-left-hero .walsh-hero-div-block { width: 100%; }
}

/* Mobile fold: the old layout spent the entire first screen on type, so a
   cold visitor saw no product and no action. Tighten the display type and
   pull the image and CTA up into view. */
@media (max-width: 767px) {
  .walsh-left-hero .walsh-heading-large-black {
    font-size: clamp(2.75rem, 13vw, 4.25rem);
    line-height: 0.88;
    letter-spacing: -0.01em;
  }

  .walsh-hero-p-wrapper .walsh-paragraph-serif-left-hero {
    font-size: 1rem;
    line-height: 1.45;
    max-width: 34ch;
    /* The measure cap makes the block narrower than its wrapper; without this
       it stays flush left while the headline and CTA are centred. */
    margin-inline: auto;
  }

  .walsh-left-hero .craft-rule { margin: 16px 0 18px; }

  .walsh-hero-div-block { margin-top: 18px; }
}

/* ---------------------------------------------------------------------------
   3. Navigation — a masthead, not a chrome bar.

   At rest it is invisible: no band, no outline, the wordmark and links
   sitting straight on the hero. It only materialises once you scroll, as a
   frosted bar under a cobalt rule.

   Two incumbent rules are overridden, both of which use !important:
   - redesign.css:568 paints .walsh-nav-wrapper-green-padding-2 with
     --bg-elevated, the full-width grey strip behind the pill;
   - redesign.css:956 gives .walsh-float-menu a 1px --border hairline, the
     pale pill outline.

   Deliberately paint-only: no size change. A transform-based condense would
   make the navbar a containing block for its own position:fixed mobile menu
   overlay, and animating padding instead would thrash layout on every scroll
   frame. Colour and backdrop-filter composite without either problem.
   --------------------------------------------------------------------------- */

.walsh-nav-wrapper-green-padding-2 {
  background-color: transparent !important;
  border-bottom: 0 !important;
  transition: background-color 420ms var(--craft-ease-io);
}

/* Nav chrome is not selectable content. Tapping the burger otherwise
   drag-selects the link labels and the App Store badge, painting them in the
   selection colour — which on this site is cobalt, so it reads as a styling
   bug rather than a selection. Also kills the grey tap-flash on iOS. */
.walsh-float-menu,
.walsh-float-menu * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.craft-nav {
  background-color: transparent !important;
  /* width 0, not just transparent: the dropdown is positioned left:0/right:0
     against the padding box, so a 1px border would inset it and the panel
     would sit 1px narrower than the pill on each side. */
  border-width: 0 !important;
  border-color: transparent !important;
  transition: background-color 420ms var(--craft-ease-io),
              backdrop-filter 420ms var(--craft-ease-io),
              border-color 420ms var(--craft-ease-io);
}

/* Nav links: a cobalt rule wipes in under the label on hover and focus, and
   stays put on the current page. Replaces the pill outline as the thing that
   says "this is navigation". */
.walsh-nav-link-black {
  position: relative;
}

.walsh-nav-link-black::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: var(--craft-rule);
  background: var(--c-accent-500);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 320ms var(--craft-ease);
}

.walsh-nav-link-black:hover::after,
.walsh-nav-link-black:focus-visible::after,
.walsh-nav-link-black.w--current::after { transform: scaleX(1); }

/* ---------------------------------------------------------------------------
   3b. Mobile dropdown — same object as the pill above it.

   redesign.css:1006 gives the panel --bg-elevated plus a --border ring and
   --radius-md, which is why it read as a separate opaque slab from a
   different system while the pill above it was frosted and borderless. It
   now takes the same frosted ground, loses the ring, and gains a shadow for
   separation instead. The pill frosts whenever the panel is open, so the two
   read as one object even at the top of the page where the pill is otherwise
   clear.

   Alpha is higher here than on the pill (0.88 vs 0.72): this panel sits over
   photography and full-strength display type, and the links have to stay
   legible. That is the concern redesign.css §9.3 raised with "must be a
   solid ink surface" — met with opacity rather than opacity 1.
   --------------------------------------------------------------------------- */

@media (max-width: 991px) {
  /* The panel emerges from the pill's vertical midpoint and runs down at the
     same width, square across the top, rounded at the foot — one shape that
     continues the pill rather than a card floating beneath it.

     The pill deliberately does NOT frost while the panel is open. Two
     translucent layers overlapping across the pill's lower half composite to
     ~0.98 alpha against 0.88 elsewhere, which prints as a dark band straight
     through the middle of the shape. Letting the panel alone carry the frost
     keeps one flat surface, and matches how the header already looks at rest
     at the top of the page. */
  /* The pill hands its surface to the panel while open. The panel spans the
     pill's full height plus the menu, so the frost is drawn once by one
     element: two overlapping translucent layers composite to ~0.98 where
     they meet and print a dark band through the shape. */
  .walsh-float-menu:has(.walsh-nav-menu-white.nav-open),
  .walsh-float-menu:has(.walsh-main-nav.mnav-open) {
    background-color: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    /* Instant, not animated. .craft-nav carries a 420ms background-color
       transition for the scroll frost; letting it run here means the pill
       fades out while the panel fades in, and the surface visibly dips and
       recovers on every open. The handover must be a swap, not a crossfade. */
    transition: none !important;
  }

  .walsh-nav-menu-white.nav-open,
  .walsh-nav-menu-white {
    transition: none !important;
  }

  /* .walsh-main-nav is position:relative, so it — not the pill — was the
     panel's containing block, offsetting top:0 by the pill's 15px padding.
     Static so the panel's coordinates are the pill's own. The only thing
     that relied on it was Webflow's .w-nav-overlay, which redesign.css:1017
     already sets to display:none.

     Scoped to the open state, NOT applied unconditionally: site.css:1846
     positions the .mnav menu absolutely against this same element, so making
     it static while closed would break the blog and compare menus, which use
     a different toggle. Both open states are covered here. */
  .walsh-main-nav:has(.walsh-nav-menu-white.nav-open),
  .walsh-main-nav.mnav-open,
  /* Blog and compare pages additionally make .walsh-inner-nav relative
     (site.css:1816) purely so the mnav menu can anchor to it. Neutralise it
     too while open, or the panel lands 15px low — the pill's padding. The
     .mnav-toggle beside it is a flex item, not absolutely positioned, so
     nothing else depends on this. */
  .mnav.mnav-open .walsh-inner-nav { position: static !important; }

  .walsh-nav-menu-white.nav-open,
  .mnav.mnav-open .walsh-nav-menu-white {
    background-color: color-mix(in srgb, var(--bg-elevated) 90%, transparent) !important;
    backdrop-filter: saturate(1.4) blur(18px);
    -webkit-backdrop-filter: saturate(1.4) blur(18px);
    border: 0 !important;
    box-shadow: 0 26px 60px -24px rgba(0, 0, 0, 0.75) !important;
    /* Covers the pill and continues below it, so the pill does not vanish
       when it hands over its background. Top corners take the pill's own
       radius — half its height, which is what a 999px radius resolves to on
       an 84px-tall pill — so the crown of the shape is identical to the pill
       it replaces. */
    top: 0 !important;
    border-radius: var(--craft-pill-half, 42px) var(--craft-pill-half, 42px)
                   28px 28px !important;
    padding-top: calc(var(--craft-pill-half, 42px) * 2 + 6px) !important;
  }

  /* The panel carries z-index 1200 (redesign.css:1027) and the brand block
     only z-index 2, so a panel that starts at the pill's midline paints over
     the lower half of the wordmark and the burger. Lift both above it: the
     panel must emerge from behind them, which is the whole illusion. */
  .walsh-brand-block,
  .walsh-menu-button-black,
  .mnav-toggle {
    position: relative;
    z-index: 1300;
  }

  /* Webflow's 15px top margin on the link row stacks on top of the padding
     that already clears the pill, opening a void under the wordmark. */
  .walsh-nav-menu-white.nav-open .walsh-flex-nav-buttons,
  .mnav.mnav-open .walsh-flex-nav-buttons {
    margin-top: 0 !important;
  }

  /* A left-anchored underline suits a horizontal row, not a stacked list.
     In the panel the same links get a cobalt wash on hover and focus. */
  .walsh-nav-menu-white.nav-open .walsh-nav-link-black::after,
  .mnav.mnav-open .walsh-nav-link-black::after { display: none; }

  .walsh-nav-menu-white.nav-open .walsh-nav-link-black:hover,
  .walsh-nav-menu-white.nav-open .walsh-nav-link-black:focus-visible,
  .mnav.mnav-open .walsh-nav-link-black:hover,
  .mnav.mnav-open .walsh-nav-link-black:focus-visible {
    background-color: color-mix(in srgb, var(--c-accent-500) 20%, transparent) !important;
  }
}

/* !important is required: redesign.css:955 pins .walsh-float-menu's
   background with !important to undo a hard-coded Webflow #fff. Without
   matching it the ground stays opaque and backdrop-filter does nothing,
   because nothing shows through to blur. */
.craft-nav.is-scrolled {
  background-color: color-mix(in srgb, var(--bg-elevated) 72%, transparent) !important;
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  /* No ring at all. The pill keeps only its frosted ground; the edge that
     appears on scroll is a full-width rule on the wrapper below, not an
     outline around the pill. */
  border-color: transparent !important;
}

/* No rule under the header either. The frosted ground is the whole signal —
   an accent line across the viewport competes with the hero instead of
   framing it. */

/* ---------------------------------------------------------------------------
   4. Reveal utility — scroll-driven, no JavaScript, no observer.
   --------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    @keyframes craft-rise {
      from { opacity: 0; transform: translateY(28px); }
      to   { opacity: 1; transform: none; }
    }

    @keyframes craft-word-in {
      from { transform: translateY(105%) rotate(2.5deg); }
      to   { transform: none; }
    }

    @keyframes craft-rule-draw {
      from { transform: scaleX(0); }
      to   { transform: scaleX(1); }
    }

    @keyframes craft-img-settle {
      from { opacity: 0; transform: scale(1.08) translateY(20px); }
      to   { opacity: 1; transform: none; }
    }

    /* Section-level entrances. Ranges are entry-based so an element that is
       already on screen at load renders finished, not mid-animation. */
    .answer__eyebrow,
    .answer__title,
    .answer__body,
    .answer__inside-label,
    .looks-gallery__header > *,
    .fcar-section > .walsh-container > *,
    .testimonials > .walsh-container > *,
    .blog-preview__header > *,
    .walsh-cta-center-wrapper > * {
      animation: craft-rise both;
      animation-timeline: view();
      animation-range: entry 8% cover 26%;
    }

    /* Staggered list — each item trails the one above it. */
    .answer__inside li,
    .proof-stat {
      animation: craft-rise both;
      animation-timeline: view();
      animation-range: entry 5% cover 30%;
    }
    .answer__inside li:nth-child(2), .proof-stat:nth-child(2) { animation-range: entry 5% cover 34%; }
    .answer__inside li:nth-child(3), .proof-stat:nth-child(3) { animation-range: entry 5% cover 38%; }
    .answer__inside li:nth-child(4), .proof-stat:nth-child(4) { animation-range: entry 5% cover 42%; }
    .answer__inside li:nth-child(5) { animation-range: entry 5% cover 46%; }

    /* Masthead words. These run on the document timeline (not scroll) because
       the hero is above the fold — it should play on arrival, once. */
    .craft-word {
      animation: craft-word-in 900ms var(--craft-ease) both;
      animation-delay: calc(var(--craft-i, 0) * 70ms);
    }

    .walsh-left-hero .craft-rule {
      animation: craft-rule-draw 700ms var(--craft-ease) both;
      animation-delay: 520ms;
    }

    .looks-gallery__img,
    .pillar__media {
      animation: craft-img-settle both;
      animation-timeline: view();
      animation-range: entry 4% cover 28%;
    }
  }
}

/* ---------------------------------------------------------------------------
   5. Looks gallery — a snapping rail whose centre frame is the largest.
   --------------------------------------------------------------------------- */

.looks-gallery__scroll {
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 24px;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.looks-gallery__scroll::-webkit-scrollbar { display: none; }

.looks-gallery__img {
  scroll-snap-align: center;
  transition: transform 600ms var(--craft-ease), filter 600ms var(--craft-ease);
}

/* Frames dim and shrink away from centre; the centred one is full strength. */
@supports (animation-timeline: view(inline)) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes craft-rail-focus {
      0%,  100% { transform: scale(0.9);  filter: saturate(0.55) brightness(0.72); }
      50%       { transform: scale(1);    filter: none; }
    }

    .looks-gallery__img {
      animation: craft-rail-focus linear both;
      animation-timeline: view(inline);
      animation-range: cover 12% cover 88%;
    }
  }
}

/* ---------------------------------------------------------------------------
   6. Pillars and feature cards — cobalt sweep on hover, cursor-tracked
   spotlight. motion.js writes --mx / --my as percentages on pointer move.
   --------------------------------------------------------------------------- */

/* Scoped to genuine cards only. .pillar is deliberately excluded:
   redesign.css:613 records that the EXPLORE/DRESS/YOU pillars are NOT cards
   but full-bleed editorial blocks sitting directly on the band, with no
   surface and no border. A spotlight there also renders as a bare rectangle
   — the panel has no background or radius to bound it — and the opaque
   .device frame inside punches a black block through the middle of it. */
.fcar-card {
  position: relative;
  isolation: isolate;
  transition: transform 500ms var(--craft-ease),
              border-color 500ms var(--craft-ease-io);
}

/* The spotlight: a soft cobalt field that follows the pointer. Pure CSS once
   the two custom properties exist; absent JS it simply never appears. */
.fcar-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  opacity: 0;
  transition: opacity 420ms var(--craft-ease-io);
  background: radial-gradient(
    340px circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--c-accent-500) 26%, transparent),
    transparent 70%
  );
}

@media (hover: hover) {
  .fcar-card:hover { transform: translateY(-4px); }
  .fcar-card:hover::after { opacity: 1; }
}

/* Keyboard parity — focus gets the same treatment as hover. */
.fcar-card:focus-within::after { opacity: 1; }

/* ---------------------------------------------------------------------------
   7. Closing CTA — the one place cobalt owns the whole field instead of
   accenting it, so the page ends on its loudest note. A slow wordmark
   marquee runs behind the copy.
   --------------------------------------------------------------------------- */

/* !important is required here: redesign.css §9.6 pins this band's background
   with !important to undo a Webflow bug that made text and ground the same
   colour. This is a deliberate override of that fix, not a new one. */
.walsh-cta-green-wrapper {
  position: relative;
  overflow: hidden;
  background-color: var(--c-accent-500) !important;
}

.walsh-cta-green-wrapper .walsh-heading-large-white,
.walsh-cta-green-wrapper .walsh-main-paragraph-white { color: var(--c-neutral-950); }

.craft-marquee {
  position: absolute;
  inset-block: auto 0;
  left: 0;
  width: 100%;
  display: flex;
  gap: 0.35em;
  font-family: Anton, Impact, sans-serif;
  font-size: clamp(4rem, 16vw, 13rem);
  line-height: 0.82;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  z-index: 0;
  /* Outlined, low-contrast — texture, never a competing headline. */
  color: transparent;
  -webkit-text-stroke: 1.5px color-mix(in srgb, var(--c-neutral-950) 26%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 55%);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 55%);
}

.craft-marquee > span { flex: 0 0 auto; }

.walsh-cta-green-wrapper .walsh-container-padding-large { position: relative; z-index: 1; }

@media (prefers-reduced-motion: no-preference) {
  @keyframes craft-marquee-run {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
  }
  .craft-marquee > span {
    animation: craft-marquee-run 38s linear infinite;
  }
}

/* ---------------------------------------------------------------------------
   8. Buttons and links — the App Store badge is the primary action on every
   screen; give it a real pressed state and a cobalt halo on hover.
   --------------------------------------------------------------------------- */

.app-store-badge {
  display: inline-block;
  border-radius: 10px;
  transition: transform 260ms var(--craft-ease),
              box-shadow 260ms var(--craft-ease);
}

@media (hover: hover) {
  .app-store-badge:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 30px -8px color-mix(in srgb, var(--c-accent-500) 65%, transparent);
  }
}
.app-store-badge:active { transform: translateY(0); }

.app-store-badge:focus-visible {
  outline: 2px solid var(--c-accent-500);
  outline-offset: 4px;
}

/* ---------------------------------------------------------------------------
   9. Reduced motion — one switch, everything off. Content stays exactly where
   it lands; only movement is removed.
   --------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .craft-word,
  .walsh-left-hero .craft-rule,
  .craft-marquee > span,
  .looks-gallery__img,
  .pillar__media,
  .hero-rota__img {
    animation: none !important;
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }

  .looks-gallery__scroll { scroll-snap-type: none; }
}

/* ---------------------------------------------------------------------------
   10. /skills/ — the Claude Skills giveaway section.

   A different audience from the rest of the site: people who install things,
   read frontmatter and want the file, not the pitch. So this section reads
   more like documentation than editorial — mono labels, a real code block,
   numbered install steps — while still standing on the same tokens as
   everything else. No new colours, no new fonts, no new stylesheet.

   It sits on top of blog.css's .journal shell (ground, measure, masthead
   atoms, .grid, .collection__head), which the hub and detail pages reuse
   verbatim. Only what .journal has no equivalent for is defined here.

   Everything below is visible by default. The one entrance animation lives
   in the @supports block at the end, and §9's reduced-motion switch already
   covers it because it targets the same properties.
   --------------------------------------------------------------------------- */

/* ---- 10.1 Section furniture ---------------------------------------------- */

.skills-section { margin-top: clamp(52px, 7vw, 92px); }

/* Two prose columns on desktop, one on mobile. Deliberately not CSS columns:
   these are separate thoughts, not a flowed measure, and column-fill would
   split a paragraph across the gutter. */
.skills-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 56px);
}

.skills-prose p {
  font-family: var(--font-body);
  font-size: clamp(15px, 1.15vw, 17.5px);
  line-height: 1.65;
  color: var(--fg-muted);
  margin: 0 0 1.15em;
  max-width: 62ch;
}

.skills-prose p:last-child { margin-bottom: 0; }
.skills-prose strong { color: var(--fg); font-weight: 600; }

.skills-prose a {
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  transition: color 0.25s ease;
}
.skills-prose a:hover { color: var(--accent); }

/* Inline code — used constantly on this page for paths like ~/.claude/skills.
   Kept to a tint rather than a filled chip so a paragraph with four of them
   does not turn into a row of boxes. */
.skills-prose code,
.skills-install code,
.skill-spec code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  color: var(--fg);
  background: color-mix(in srgb, var(--c-neutral-500) 18%, transparent);
  border-radius: 4px;
  padding: 0.12em 0.36em;
  /* Long paths must be allowed to break rather than push the page sideways. */
  overflow-wrap: anywhere;
}

.skills-lede {
  font-family: var(--font-body);
  font-size: clamp(17px, 1.5vw, 22px);
  line-height: 1.55;
  color: var(--fg);
  max-width: 46ch;
  margin: 0 0 clamp(24px, 3vw, 36px);
}

/* Mono aside — the "this is not what Stylin does" line, and the note under
   the code block. Small, quiet, always secondary. */
.skills-note {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.65;
  letter-spacing: 0.02em;
  color: var(--fg-subtle);
  margin: 14px 0 0;
}

/* ---- 10.2 Install steps -------------------------------------------------- */

/* A counter rather than a list marker: the number is display type sitting in
   its own column, which is the whole visual idea. list-style would put it in
   the text flow at body size. */
.skills-install {
  list-style: none;
  counter-reset: skills-step;
  margin: 0;
  padding: 0;
}

.skills-install > li {
  counter-increment: skills-step;
  position: relative;
  padding: 0 0 0 clamp(38px, 4vw, 52px);
  margin: 0 0 clamp(20px, 2.4vw, 30px);
}

.skills-install > li:last-child { margin-bottom: 0; }

.skills-install > li::before {
  content: counter(skills-step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.05em;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  color: var(--accent);
}

.skills-install__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.35;
  color: var(--fg);
  margin: 0 0 6px;
}

.skills-install__body {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  color: var(--fg-muted);
  margin: 0;
  max-width: 56ch;
}

/* ---- 10.3 Code block ----------------------------------------------------- */

/* The SKILL.md itself. Selectable and fully readable with JS off — the copy
   button is added by js/copy-code.js and is [hidden] until then, so nothing
   here depends on script. */
.skills-codeblock {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  overflow: hidden;
  margin: 0;
}

.skills-codeblock__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--c-neutral-500) 10%, transparent);
}

.skills-codeblock__name {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--fg-subtle);
}

.skills-copy {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  padding: 5px 12px;
  cursor: pointer;
  transition: border-color 0.25s ease, color 0.25s ease,
              background-color 0.25s ease;
}

.skills-copy:hover,
.skills-copy:focus-visible {
  color: var(--accent-fg);
  background: var(--accent);
  border-color: var(--accent);
}

.skills-copy[data-state="copied"] {
  color: var(--accent);
  border-color: var(--accent);
  background: transparent;
}

.skills-codeblock pre {
  margin: 0;
  padding: clamp(14px, 2vw, 22px);
  /* The one place on the page allowed to scroll sideways — a SKILL.md line
     must not be re-wrapped, and the page body must never scroll instead. */
  overflow-x: auto;
  max-height: 620px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.skills-codeblock code {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.65;
  color: var(--fg);
  white-space: pre;
  background: none;
  padding: 0;
}

/* ---- 10.4 Skill cards ---------------------------------------------------- */

/* Sits inside blog.css's .grid, so column count and gaps are already handled.
   These cards carry no photography — there is nothing to photograph about a
   markdown file — so the index number does the work the image would. */
.skill-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-decoration: none;
  color: inherit;
  padding: clamp(20px, 2.2vw, 28px);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--c-neutral-500) 7%, transparent);
  transition: border-color 0.3s var(--craft-ease-io),
              transform 0.4s var(--craft-ease),
              background-color 0.3s var(--craft-ease-io);
}

.skill-card__index {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--accent);
}

.skill-card__title {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.2rem, 1.55vw, 1.5rem);
  line-height: 1.12;
  letter-spacing: -0.008em;
  color: var(--fg);
  margin: 0;
  transition: color 0.25s ease;
}

.skill-card__dek {
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--fg-muted);
  margin: 0;
}

.skill-card__slug {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--fg-subtle);
  margin-top: auto;
  padding-top: 8px;
  overflow-wrap: anywhere;
}

@media (hover: hover) {
  .skill-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent);
    background: color-mix(in srgb, var(--c-accent-500) 9%, transparent);
  }
}
.skill-card:hover .skill-card__title,
.skill-card:focus-visible .skill-card__title { color: var(--accent); }

.skill-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ---- 10.5 Buttons and the bundle band ------------------------------------ */

.skills-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  text-decoration: none;
  padding: 14px 22px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--accent-fg);
  transition: transform 0.26s var(--craft-ease),
              background-color 0.26s var(--craft-ease-io),
              box-shadow 0.26s var(--craft-ease);
}

@media (hover: hover) {
  .skills-btn:hover {
    transform: translateY(-2px);
    background: var(--c-accent-700);
    box-shadow: 0 10px 30px -10px color-mix(in srgb, var(--c-accent-500) 70%, transparent);
  }
}
.skills-btn:active { transform: translateY(0); }
.skills-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.skills-btn--ghost {
  background: transparent;
  color: var(--fg);
  border-color: var(--border-strong);
}
@media (hover: hover) {
  .skills-btn--ghost:hover {
    background: transparent;
    border-color: var(--accent);
    color: var(--accent);
    box-shadow: none;
  }
}

.skills-btnrow {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/* The download-everything band. Cobalt-bordered rather than cobalt-filled:
   the closing Stylin CTA is the loudest thing on the page and this must not
   compete with it. */
.skills-bundle {
  margin-top: clamp(52px, 7vw, 92px);
  padding: clamp(26px, 3.4vw, 44px);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--c-accent-500) 8%, transparent);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(20px, 3vw, 40px);
  align-items: center;
}

.skills-bundle__title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-weight: 400;
  font-size: clamp(1.7rem, 3.4vw, 2.9rem);
  line-height: 0.95;
  color: var(--fg);
  margin: 0 0 10px;
}

.skills-bundle__dek {
  font-family: var(--font-body);
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--fg-muted);
  margin: 0;
  max-width: 52ch;
}

/* ---- 10.6 Detail-page furniture ------------------------------------------ */

/* Not .journal__title. That headline tops out at 8.5rem, which is right for a
   two-word hub masthead and wrong for "Wardrobe Cost-Per-Wear Tracker" — at
   that size the longest of the ten titles runs to four stacked lines and
   pushes everything else off the first screen. Same Anton, same uppercase,
   capped low enough that every one of the ten sits in two lines or fewer. */
.skill-detail__title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-weight: 400;
  font-size: clamp(2.3rem, 5.4vw, 4.6rem);
  line-height: 0.94;
  letter-spacing: 0.005em;
  color: var(--fg);
  margin: 0 0 clamp(18px, 2.4vw, 26px);
  max-width: 16ch;
}

.skill-detail__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  padding: 16px 0;
  margin: clamp(22px, 3vw, 32px) 0 0;
  border-block: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-subtle);
}

.skill-detail__meta b {
  color: var(--fg);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0.06em;
}

/* "When to use it" / "What it returns" — short, scannable, not prose. */
.skill-spec {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.skill-spec > li {
  position: relative;
  padding-left: 22px;
  font-family: var(--font-body);
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--fg-muted);
  max-width: 62ch;
}

.skill-spec > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 10px;
  height: var(--craft-rule);
  background: var(--accent);
}

.skill-spec > li strong { color: var(--fg); font-weight: 600; }

/* A worked example: what the user says, then what comes back. */
.skill-example {
  border-left: var(--craft-rule) solid var(--accent);
  padding: 4px 0 4px clamp(16px, 2vw, 26px);
  margin: 0 0 clamp(22px, 2.6vw, 32px);
}

.skill-example__label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--fg-subtle);
  margin: 0 0 8px;
}

.skill-example__say {
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.6;
  color: var(--fg);
  margin: 0 0 14px;
}

/* ---- 10.7 Responsive ----------------------------------------------------- */

@media (max-width: 860px) {
  .skills-cols { grid-template-columns: 1fr; }
  .skills-bundle { grid-template-columns: 1fr; }
}

/* ---- 10.8 Entrance ------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .skill-card,
    .skills-section > .skills-cols > *,
    .skills-bundle {
      animation: craft-rise both;
      animation-timeline: view();
      animation-range: entry 5% cover 28%;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .skill-card,
  .skills-bundle {
    animation: none !important;
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
}
