/* apps/net directory-only styles.
   ---------------------------------------------------------------------------
   .net is a SIBLING of .com, not a copy of it. It loads the same compiled
   app.css so the two are unmistakably the same family, then overrides the
   tokens and type treatment below so you know at a glance which surface you are
   on. The distinction is deliberate and follows what each site is FOR:

     .com  a product. Warm near-black, gold, Fraunces editorial serif, generous
           vertical rhythm. It wants you to act.
     .net  a reference. Cooler, slightly deeper ground; a steel accent for
           interactive text with gold reserved for the brand mark alone; a sans
           display face and a tighter rhythm. It wants you to scan and browse.

   Keep new directory styling on this side of the line — if a change would look
   equally at home on .com, it probably belongs in app.css instead. */

/* The header is position: sticky, so an in-page jump puts the target heading
   UNDERNEATH it. Measured after clicking "Cities": the h2 "Browse by city" sat at
   y=36-63 with the header's bottom edge at y=61 — two pixels of heading visible at
   375px, thirteen at 1280px, and its eyebrow entirely hidden. A visitor clicks the
   main browse link and lands on an unlabelled card with clipped letters above it.

   scroll-padding-top on the scrolling element fixes every anchor at once, present
   and future, which is why it is here rather than as scroll-margin on #cities and
   #shoots. 76px is the 61px header plus breathing room. */
html { scroll-padding-top: 76px; }

:root {
  /* Cooler, deeper ground than .com's warm near-black. */
  --bg: #090a0e;
  --panel: #121419;
  --panel2: #171a21;
  --line: #232733;
  --line2: #333949;
  --ink: #e9ecf2;
  --muted: #a6adbb;
  --faint: #7f8797;

  /* Steel is the DIRECTORY's accent, end to end. An earlier revision of this
     file held gold back "for the brand mark and the one cross-network handoff";
     the owner reversed that — each property owns its accent completely and the
     network reads as one family through structure, not one colour. */
  --steel: #7fb4d8;
  --steel-soft: #a9cde6;

  /* .com's accent tokens, re-pointed at steel. app.css carries roughly 200 gold
     rules and .net renders a moving subset of them, so overriding each one by
     hand loses: the focus ring, the section dividers, the showreel label, the
     stat band and the footer's own "Videographer.net" name were all still gold
     after a selector-by-selector pass. Re-pointing the token is the end-to-end
     fix, and a gold rule added to app.css tomorrow lands steel here for free.
     Only literal gold hex values in app.css still need naming below. */
  --gold: #7fb4d8;
  --gold2: #a9cde6;
}

/* HEADINGS ARE FRAUNCES HERE, THE SAME AS THE OTHER TWO. This block used to
   override them to the sans face at a smaller size and heavier weight, justified
   with "a directory is scanned, not read". That was my reasoning, not the brand's,
   and the owner spotted it immediately: the .net header does not match .com or .org
   and it should.

   Measured across all three at 1280px before removing it:
     .com  h1  Fraunces 59.2px w560 ls -1.184px
     .org  h1  Fraunces 59.2px w560 ls -1.184px
     .net  h1  system-ui 38.4px w700 ls -0.806px

   Two properties agreeing exactly and one differing on all four axes is not a
   distinction, it is a defect. docs/brand/IDENTITY.md settles it: Display is
   Fraunces, for "headlines and the wordmark", listed once for the system — and it
   names exactly one deliberate cross-property exception (.org's gold btn-com) with
   the instruction "Do not add a second." I had added a second.

   The eyebrow above the h1 was already correct and identical on all three — mono,
   12.16px, w400, 1.7px tracking, uppercase — with only the accent colour differing,
   which is exactly the axis a property IS allowed to own. That is what the
   divergence should have looked like: same shape, own colour.

   Deleted rather than corrected to matching values, for the reason .org's specificity
   trap taught all three of us tonight: a local copy of a shared rule silently pins
   this property the day .com revisits theirs. Nothing here now means .net follows. */


/* The structure was the real gap. .com and .org both open eyebrow -> h1 -> lede
   and .net opened on a bare h1 — so the thing the owner praised about .com's
   hero was the one part missing here. */
.home-hero .eyebrow { font-family: var(--mono); font-size: .76rem; letter-spacing: .14em; text-transform: uppercase; margin-bottom: 1rem; }
.section + .section { margin-top: clamp(2.6rem, 5vw, 4rem); }

/* The same gap after a listing grid. `.section + .section` never matched on the
   four directory pages, because what precedes the editorial there is `.dir-grid`,
   not a section — so the seam measured 7px on /videographers against 49-71px for
   the identical transition on the home page. "How a listing gets here" collided
   with the bottom of the last card and read as part of that card rather than as a
   new section. It was the only place on the site where the vertical rhythm broke,
   which is exactly why it stood out. */
.dir-grid + .section { margin-top: clamp(2.6rem, 5vw, 4rem); }

/* Interactive text is steel here; .com's gold links would read as one site.
   Buttons included: gold CTAs on a steel page read as .com's buttons pasted
   onto the directory. Each property owns its own accent end to end — the
   network reads as one family through structure, not one colour.

   EXCEPT the network components, and that exclusion is why Corey saw a blue
   wordmark in my footer. These two selectors are 0,3,1; `.nw-name` is 0,1,0. So a
   blanket "every link on this property is steel" quietly out-specified the shared
   network block and repainted "Videographer" in .net's accent, leaving the suffix
   its own colour — ink+gold rendered as steel+gold. Measured before the fix:
   rgb(127,180,216) where --ink is rgb(233,236,242).

   The exclusion is an ATTRIBUTE SUBSTRING, not a class list, and that is the whole
   lesson from the three of us hitting this in one evening. .org excluded `.nw-name`
   by name; .com shipped the network LINE the same day, whose anchors are `.nl-to
   nw-com`, and the named exclusion had never heard of it. .com then proposed
   `color: revert`, which .org measured and rejected — revert rolls back the cascade
   ORIGIN, so those anchors take the user-agent blue rather than the .nw-com
   underneath. A rule has to stop MATCHING; undoing the value lands somewhere else.

   Every network anchor in both components carries a class containing "nw-" —
   nw-name, nl-to nw-com, nl-here nw-org — so one selector covers the family and
   whatever .com ships next. .org landed the same fix in 6e052ab; this is .net's
   half, deliberately identical so the next person finds one pattern and not three. */
.wrap a:not(.brand):not(.btn):not([class*="nw-"]),
.container a:not(.brand):not(.btn):not([class*="nw-"]),
.section-lede a, .dir-crumbs a, .dir-see-all,
.city-index a, .ml-prose a { color: var(--steel); }
.wrap a:not(.brand):not(.btn):not([class*="nw-"]):hover,
.container a:not(.brand):not(.btn):not([class*="nw-"]):hover,
.dir-crumbs a:hover { color: var(--steel-soft); }
.brand { color: var(--ink); }

/* The footer names all three properties and marks the one you are on. On .com
   that mark is gold against gold links, which still reads; here every link is
   steel, so a steel "you are here" was invisible. Plain ink instead — it is the
   one name in the list that is not a link, and now it looks like it. */
.nw-name.is-here { color: var(--ink); }

/* Steel CTAs. --steel is light, so the label goes dark for contrast. */
.btn-gold { background: var(--steel); color: #08131c; }
.btn-gold:hover { background: var(--steel-soft); color: #08131c; box-shadow: 0 4px 16px -6px rgba(127,180,216,.5); }
.btn-gold:active { background: var(--steel); box-shadow: none; }
.site-nav a.btn-gold { color: #08131c; }
.eyebrow { color: var(--steel); }
.dir-card-cta { color: var(--steel); }
.dir-card:hover, .dir-tile:hover, .dir-chip:hover { border-color: var(--steel); }
.dir-card:hover .dir-card-play { background: var(--steel); border-color: var(--steel); color: #0b1016; }
.pf-stat-n { color: var(--steel); }

/* The plain (outline) button. Its border and label follow the tokens above, but
   app.css tints its hover background with a literal gold rgba, which the token
   alias cannot reach. .net renders this button on listings and on 404. */
.btn:hover { background: rgba(127,180,216,.07); }

/* The .net mark is STEEL, not gold. Gold was held back as the one shared
   network token, but a gold ".net" on a steel site read as a .com artifact
   rather than a sibling property. Owner call: the logo matches the palette it
   sits in — the network reads as one family through structure, not one colour. */
.brand b { color: var(--steel); }

.dir-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}

.dir-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line, rgba(255, 255, 255, .12));
  border-radius: 14px;
  background: var(--panel, rgba(255, 255, 255, .02));
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow, 0 12px 34px -18px rgba(0,0,0,.7));
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.dir-card:hover { border-color: var(--steel); transform: translateY(-3px); box-shadow: var(--shadow-lift, 0 26px 60px -26px rgba(0,0,0,.8)); }
.dir-card-media { position: relative; aspect-ratio: 16/9; display: flex; align-items: center; justify-content: center; background: linear-gradient(140deg, #262c38, #151922); overflow: hidden; }
.dir-card-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .4s cubic-bezier(.2,.6,.2,1); }
.dir-card:hover .dir-card-media img { transform: scale(1.05); }
.dir-card-media::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(11,11,13,.1) 55%, rgba(11,11,13,.55)); }
/* A CARD WITH NO REEL COLLAPSES INSTEAD OF RESERVING A VOID. Measured at 375px on
   /videographers: every .dir-card-media was 192px tall and three of four contained
   nothing but a small film glyph centred in the space — 576px of empty box in one
   scroll. On a directory about VIDEO that undercuts the product at a glance, and it
   reads as a page still loading.

   The 16/9 box exists to hold a frame. With no frame there is nothing to hold, so
   the aspect-ratio is dropped and the strip sizes to its own content. The glyph
   stays, smaller, as a label rather than a placeholder: a card that says "no reel"
   in one line is honest, where a card that reserves a widescreen hole for a reel
   that does not exist is a promise the grid cannot keep.

   Cards without work are now visibly SHORTER than cards with it, which is also the
   truthful ranking signal — the grid stops presenting a crawled stub and a studio
   with four films as equally substantial. */
.dir-card-noreel {
  aspect-ratio: auto;
  min-height: 0;
  padding: .5rem 0;
  gap: .5rem;
}
.dir-card-noreel i { color: var(--faint, #81776f); font-size: 1rem; }

/* The gradient scrim is for legibility over a photograph. There is no photograph. */
.dir-card-noreel::after { content: none; }
.dir-card-play { position: relative; z-index: 2; width: 44px; height: 44px; border-radius: 50%; background: rgba(11,11,13,.45); border: 1.5px solid rgba(255,255,255,.85); display: flex; align-items: center; justify-content: center; color: #fff; font-size: .8rem; }
.dir-card:hover .dir-card-play { background: var(--steel); border-color: var(--steel); color: #0b1016; }
.dir-card-body { display: flex; flex-direction: column; gap: .35rem; padding: 1rem 1.1rem 1.1rem; }
.dir-card-name { font-weight: 700; font-size: 1.02rem; color: var(--ink, #efe9df); }
.dir-card-loc { font-size: .84rem; color: var(--muted, #b5aaa1); } .dir-card-loc i { color: var(--steel); margin-right: .35rem; }
.dir-card-types { font-family: var(--mono, monospace); font-size: .72rem; color: var(--faint, #81776f); }
.dir-card-foot { display: flex; align-items: center; justify-content: space-between; margin-top: .5rem; }
.dir-card-chip { font-family: var(--mono, monospace); font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted, #b5aaa1); border: 1px solid var(--line2, rgba(255,255,255,.15)); border-radius: 20px; padding: .12rem .5rem; }
.dir-card-cta { font-size: .84rem; font-weight: 600; color: var(--steel); display: inline-flex; align-items: center; gap: .35rem; }

.dir-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: .85rem;
  margin-top: 1.25rem;
}
.dir-tile {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--line, rgba(255, 255, 255, .12));
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
  transition: border-color .15s ease;
}
.dir-tile:hover { border-color: var(--steel); }
.dir-tile-name { font-weight: 600; }
/* An explicit colour, not faded steel. directory.css:59 colours every non-brand
   anchor steel, so this inherited steel and then opacity:.65 knocked it down to
   rgb(86,121,145) on the page ground — 4.25:1, under the 4.5:1 AA needs at
   13.1px, and the only text-contrast failure on the site. --muted is 8.78:1 and
   reads as the same visual hierarchy without fading a colour to get there. */
.dir-tile-count { font-size: .82rem; color: var(--muted); }

.dir-chips { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.1rem; }
.dir-chip {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .9rem;
  border: 1px solid var(--line, rgba(255, 255, 255, .12));
  border-radius: 999px;
  text-decoration: none;
  color: inherit;
  font-size: .9rem;
  transition: border-color .15s ease;
}
.dir-chip:hover { border-color: var(--steel); }
.dir-chip span {
  font-size: .78rem;
  opacity: .7;
  background: var(--card, rgba(255, 255, 255, .06));
  border-radius: 999px;
  padding: .05rem .45rem;
}

/* Hero spacing. The owner spotted this before any of us measured it: .com and
   .org both put the first hero element 65px below the header, and .net put its
   h1 at 24px — the page read as starting before it was ready.

   The 1.5rem top margin WAS the whole gap, because there was no padding. So the
   fix is not an extra rule — a second .home-hero rule earlier in this file lost
   to this one and stacked when it did land, which is how a spacing fix becomes a
   second spacing bug. This one rule owns the hero box.

   The clamp is .com's own, from _home.scss, rather than a pixel value that would
   match at 1280 and nowhere else. */
.home-hero { margin: 0 0 2rem; padding-top: clamp(2rem, 6vw, 3.6rem); }

/* "Are you a videographer?" claim band (home + listing footers). */
.dir-claim { display:flex; align-items:center; justify-content:space-between; gap:1.2rem; flex-wrap:wrap; background:linear-gradient(180deg,var(--panel),var(--panel2)); border:1px solid var(--line2); border-left:3px solid var(--steel); border-radius:12px; padding:1.2rem 1.35rem; }
.dir-claim > div { color:var(--muted); max-width:42rem; line-height:1.5; }
.dir-claim .pf-claim-eyebrow { display:block; font-family:var(--mono); font-size:.64rem; text-transform:uppercase; letter-spacing:.12em; color:var(--steel); margin-bottom:.3rem; }

.dir-claim--price { margin-top: 2rem; }

/* Cross-domain (→ videographer.com) affordance. Opt-in, and only on the handoffs
   that carry no arrow glyph of their own, so the marker stays meaningful. */
a.ext::after { content: " ↗"; font-size: .75em; opacity: .55; margin-left: .1rem; }

/* Breadcrumb trail — directory-native orientation on deep pages. */
.dir-crumbs { margin: 0 0 1rem; }
.dir-crumbs ol { list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: .1rem; padding: 0; margin: 0; font-size: .82rem; }
.dir-crumbs li { display: inline-flex; align-items: center; color: var(--faint); }
.dir-crumbs li:not(:last-child)::after { content: "/"; margin: 0 .55rem; color: var(--line2); }
.dir-crumbs a { color: var(--muted); } .dir-crumbs a:hover { color: var(--steel-soft); }
.dir-crumbs li[aria-current] span { color: var(--ink); }

/* Section header with a right-aligned "see all" affordance. The colour comes
   from the steel link rule above — this rule used to restate it as var(--gold2)
   and, sitting later in the file at equal specificity, quietly won. */
.dir-head-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; }
.dir-see-all { flex: 0 0 auto; font-weight: 600; font-size: .9rem; white-space: nowrap; }
.dir-see-all:hover { text-decoration: underline; }
.dir-more { margin-top: 1.6rem; }

/* The 404 is the one centred page. It used to carry two inline style attributes,
   which doctrine build-hygiene-no-inline forbids. */
.dir-404 { text-align: center; }
.dir-404 .pf-actions { justify-content: center; }

/* ── Listing mini-site — the studio's narrative home in the directory. A
   prose-forward "little site", DISTINCT from .com/p/:slug (the tight product
   profile). Wide container; reading prose capped for legibility. ───────────── */
.ml { max-width: 60rem; margin: 0 auto; }
.ml-hero { margin: 0 0 1.6rem; }
.ml-hero h1 { margin: 0 0 .5rem; }
.ml-tagline { font-size: 1.2rem; color: var(--muted); line-height: 1.5; max-width: 46ch; margin: 0 0 1rem; }
.ml-metarow { display: flex; flex-wrap: wrap; gap: .6rem; margin: 0 0 1.2rem; }
.ml-chip { display: inline-flex; align-items: center; gap: .45rem; font-size: .86rem; color: var(--muted); border: 1px solid var(--line2); border-radius: 999px; padding: .35rem .8rem; }
.ml-chip i { color: var(--steel); }
.ml-reel { margin: 0 0 1.6rem; }
.ml-stats { margin: 0 0 2rem; }
.ml-about, .ml-work, .ml-cover { margin: 2.4rem 0; }
.ml-prose { color: var(--muted); font-size: 1.08rem; line-height: 1.7; max-width: 66ch; margin: 0; }
.ml-cover-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-top: 1rem; }
@media (max-width: 560px) { .ml-cover-grid { grid-template-columns: 1fr; } }
.ml-cover-grid h3 { font-size: .95rem; color: var(--ink); margin: 0 0 .6rem; }
.ml-list { list-style: none; padding: 0; margin: 0; display: grid; gap: .5rem; }
.ml-list li { display: flex; align-items: center; gap: .55rem; color: var(--muted); font-size: .95rem; }
.ml-list li i { color: var(--steel); width: 1rem; text-align: center; }

/* ── The request console (apps/com/app/pages/kit.js, teaser mode) ────────────
   Its chrome is styled by app.css under .home-main and follows the token alias
   above. These three declarations are the ones app.css writes as literal gold
   hex, which no token can reach. */
/* NO .jn OVERRIDE. It used to say `.home-main .jn { color: var(--steel-soft) }`,
   which recoloured the NUMBER spans in the console's parsed readout and left the
   STRING spans on .com's literal gold. Measured at 1280px: .com renders js and jn
   both rgb(240,196,110); .net rendered js gold and jn rgb(169,205,230). A
   half-converted syntax palette is worse than either whole one — the same readout
   showing "wedding" gold and 360 blue reads as a rendering fault rather than a
   theme.

   Dropped rather than completed, and that is the same call I got wrong with the
   44px tap targets three hours ago: the console is .com's component, its palette is
   .com's, and one property repainting half of it locally is the divergence, not the
   fix. OPEN.md asked for exactly this.

   The remaining difference is legitimate and stays: .jp punctuation resolves warm
   on .com and cool here because .net remaps the shared TOKENS, which is the one
   axis a property owns. What it may not do is override a literal.

   Worth a ruling though, and it is .com's: the strings in that pane are gold on a
   steel property, because app.css writes them as a literal hex no token can reach.
   Consistent with .com and slightly foreign here. Raised, not acted on. */
.home-main .cta { color: #08131c; }
.home-main .cta:hover { box-shadow: 0 4px 16px -6px rgba(127,180,216,.55); }

/* DELIBERATELY NO FOCUS DECORATION on the description box, and do not add one.

   This rule used to restore a ring here, on the reasonable-looking grounds that
   .com's stylesheet cancels its own. The premise was wrong, and .com has since
   removed the ring on purpose: a multi-line text input ALREADY shows focus
   through its caret, which is what every terminal relies on, and a box drawn
   around a deliberately borderless console input reads as a form control bolted
   into a terminal. It was rejected on sight twice on .com and once here.

   Every other input, textarea and select keeps its ring from app.css. This one
   element does not need a second signal on top of its own cursor. */
.home-main #describe:focus, .home-main #describe:focus-visible { outline: 0; box-shadow: none; }

/* The console is a handoff, not a directory feature, so it sits in a quieter
   band below the browse sections rather than in the hero. */
.dir-request { margin-top: 1.25rem; }

/* --- polish pass: found by auditing a running page, not by reading source ----
   Every rule below fixes something measured in a real browser at 375/768/1280. */

/* The footer headings are h2 for document structure (see shell.js) and this keeps
   them the size they have always looked. .72rem rather than the 11.2px they were:
   below about 12px is uncomfortable on a phone, and these are the only headings
   in the footer. */
.site-footer .ftr-h { font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 0 0 .5rem; }

/* Three .net-owned rules sat at 10.2-11.5px. Nudged to a 12px floor: these carry
   real information — what a studio shoots, how many pieces of work it has, and
   the claim-your-listing prompt — so they were the smallest text on the page
   saying some of the most useful things on it. */
.dir-card-types { font-size: .78rem; }
.dir-card-chip { font-size: .75rem; }
.dir-claim .pf-claim-eyebrow { font-size: .75rem; }

/* Resting-state boundaries. The two primary browse affordances had a transparent
   background, so a 1px --line border was the only thing defining them: 1.41:1,
   under the 3:1 that WCAG 1.4.11 asks of a control boundary. Hover already goes
   steel; this makes them visible before you touch them. */
.dir-tile, .dir-chip { border-color: var(--line2); background: rgba(255,255,255,.02); }

/* The primary CTA wrapped to three lines at 375px — "Route / my request / →" —
   because .com's .cactions is a flex row with no wrap. .net already overrides
   .home-main rules here, so fixing it on this property needs no boundary crossing;
   .com should still fix the row itself. */
@media (max-width: 560px) {
  .home-main .cactions { flex-wrap: wrap; }
  .home-main .cactions #route { width: 100%; justify-content: center; }
}

/* Decorative arrow on external links. a.ext::after injects " ↗" into the
   accessible name, so the nav CTA announced as "Request, north east arrow".
   Marking it presentational keeps the glyph and drops it from the name. */
a.ext::after { speak: never; }

/* Tap targets. Measured at 375px: the footer legal links were 36.7x20.5 ("Terms"),
   43.6x20.5, 48x20.5 — three ~20px-tall links sitting next to each other — the
   footer column links 176x28.9, and the breadcrumb links ~50x21. WCAG 2.5.8 asks
   24px minimum and platform guidance says 44; padding buys the height without
   moving anything visually, since these all sit in their own rows.

   Applied only on touch-sized viewports: on a desktop pointer these are already
   comfortable and the extra vertical rhythm would loosen the footer. */
@media (max-width: 700px) {
  /* REVERTED FROM 44 TO 24, AND MOSTLY REMOVED. I read WCAG 2.5.8 as if it were
     2.5.5: the AA minimum is 24x24, and 44 is 2.5.5 Enhanced, which is AAA. So I
     measured .com's 32px legal row, called it "under the 2.5.8 minimum", raised
     .net to 44 and told .org to do the same — and both did. A fix for a
     non-problem, which produced the exact divergence I was arguing against in the
     same hours. Doctrine node tap-targets-24-not-44.

     Measured with every one of my pins stripped, at 375px across seven page types:
     the ONLY .net control that actually falls under the AA line is the breadcrumb
     row, at 21px. `.ed-links a`, `.dir-chip`, `.ml-list a`, `.dir-claim .btn`,
     `.ftr-cols a` and `.dir-more a` were all compliant on the shared sheet without
     me. Eight local overrides, one of them needed.

     inline-flex ONLY where the links genuinely share a line.

     `.ftr-legal-left a` was added the moment that span stopped holding only a
     copyright notice. Matching .com's legal row put three developer links in there
     — For agents, API docs, llms.txt — and they rendered 32px on all six page
     types, 18 findings in one probe run. The rule named the RIGHT-hand span by
     class, so links added to the left-hand one were never covered. Naming a
     container rather than a role is how a rule stops applying without anyone
     editing it. */
  .site-footer .ftr-legal-links a,
  .site-footer .ftr-legal-left a,
  .dir-crumbs a { display: inline-flex; align-items: center; min-height: 24px; }

  /* THE FOOTER COLUMNS ARE NOT ONE OF THOSE, and this rule used to say they were.
     app.css sets `.ftr-cols a { display: block }`; making them inline-flex here put
     them on a shared line, and the footer markup has no whitespace between
     </a><a>, so on every mobile page the navigation rendered as "By cityBy shoot
     type" and "List freeSecond shooters". Two runs of English jammed into one word.

     The comment above this block asserted "these all sit in their own rows" — it
     was true when it was written and the rule underneath it is what stopped it
     being true. An assertion in a comment is not a check.

     flex, not block: keeps the 44px tap target the rule exists for, and restores
     the row per link. */
  .site-footer .ftr-cols a { display: flex; align-items: center; }

  /* The legal row is three links in a line, so they need horizontal separation
     too — 44px of height with touching edges is still a mis-tap. */
  .site-footer .ftr-legal-links { display: flex; flex-wrap: wrap; gap: 0 1.25rem; }
}

/* Four more sub-12px rules, all declared in .com's app.css and all rendering on
   .net. Overridden here rather than there because each one is a .net judgement
   about .net's own type scale, and app.css is .com's file — but .com should look
   at its own copies of these too.

   .eyebrow renders on EVERY page ("videographer.net · directory"), so it was the
   most-seen text on the property at 11.5px. .rf-label ("Showreel") at 10.2px was
   the smallest text on the listing, which is .net's only content page. */
.eyebrow { font-size: .78rem; }
.p-profile .rf-label { font-size: .78rem; }
.p-profile .pf-stat-l { font-size: .76rem; }

/* Tap targets measured at 375px: the footer brand mark was 139x20, the three
   network-block rows 375x24, and the listing's "More videographers" link 245x18.
   The network block is .com's markup (network.footer.js) so only its presentation
   is touched here — the rows are already full-width, they just had no height. */
@media (max-width: 700px) {
  .ftr-network .nw-name,
  .dir-more a { display: inline-flex; align-items: center; }

  /* Each network row is a name plus a description; giving the row the height keeps
     the name and its line together instead of stretching only the link. */
  .ftr-network li { padding: .25rem 0; }
}

/* The pass above says "remaining", and it was wrong: it measured the FOOTER and
   then generalised. A re-measure at 375px that printed each element's CSS path
   instead of just its text found two targets it had never looked at — the header
   wordmark at 139x27 and `.ed-links a` at 26px.

   NEITHER override lives here any more, for two different reasons.

   The wordmark is .com's now: `_base.scss` carries a bare, unconditional
   `.brand { display: inline-flex; align-items: center; min-height: 44px }`, compiled
   into the `build/app.css` that all three properties load (ba63b23). Keeping a .net
   copy of a rule with the same value would be dead CSS that silently pins this
   property if .com ever revisits theirs — and .org just lost time to exactly this
   class of problem in reverse, where a LOCAL `.site-footer .brand` at 24px beat
   .com's shared bare `.brand` on specificity and kept one property broken.
   Duplicating a shared fix per property is how that trap gets built.

   `.ed-links a` moved down beside the `.ed-links` rules, because at equal
   specificity a media query wins on source order alone and the base rule is a
   hundred lines further down this file.

   NOT changed, deliberately: links inline in running prose — "browse by city" in a
   lede (20px) and the property names inside the network fold's sentences (18px).
   WCAG 2.5.8 exempts a link whose target is inline in a sentence, and padding those
   to 44px would space out the prose to fix something the guideline says is not a
   problem. .com swept their own property and reached the same conclusion: four hits
   under 24, zero genuine failures once context was checked. */
}

/* The three macOS traffic-light dots in the console's title bar. They are pure
   window chrome on a page whose visitor is hiring a videographer, and doctrine
   interface-simplicity names exactly this: "no fake status ornaments".

   This is a deliberate exception to my own rule about not restyling .com's shared
   components on .net alone. The type scale inside the console I left to .com,
   because that is a taste question and diverging it would just make one component
   look like three. An ornament doctrine forbids is different: leaving it is
   non-compliance, not consistency. .com owns the real fix in kit.js and has been
   told; this hides it here meanwhile. */
.dir-request .cbar .d { display: none; }

/* The dots were the only thing in the left of that bar, so the bar needs its own
   padding back or the label sits against the edge. */
.dir-request .cbar { padding-left: 1rem; }

/* THE JSON PANE IS BACK. I hid it here and the owner asked why .net does not show
   it when .com does — which is the answer to the question.

   My argument was that in teaser mode the parse is not actionable, so raw JSON is
   a developer artefact in front of someone hiring a camera crew. What that missed:
   the parse IS the product. It is the one thing that makes the page read as an
   engine rather than a contact form — you type a sentence and it shows you it
   understood. Removing it takes away the demonstration of the only differentiated
   capability the network has.

   And the divergence itself was the bigger mistake. The same component behaving
   two ways across .com and .net is exactly what one-network-three-properties
   exists to prevent, and it landed right after the owner asked for the form to be
   MORE prominent on .net. I answered that by hiding half of it.

   The fake status ornaments below are a different question and stay hidden:
   .cstate displays "live" when nothing is live (the parse is a local regex) and
   the right-hand one is the literal static string "request-builder" dressed as a
   readout. interface-simplicity names those specifically. They are kit.js, so
   .com owns the real fix — hiding a doctrine violation is not the same call as
   editing the product's signature feature out of one property. */
.dir-request .cstate { display: none; }

/* The unclaimed-listing disclosure. Deliberately NOT styled like the CTA strip it
   sits above: that one is selling something, this one is telling you where the
   page came from. Steel would read as promotion, so it gets the muted treatment
   and a quiet left rule — the visual language of a footnote, which is what it is.

   It exists because real-assets-only cuts both ways: "every listing is a real
   videographer" stays true of a crawled record, but a page that cannot tell a
   crawled record from a self-created one implies these businesses put themselves
   here. One implied endorsement discredits every real listing on the site. */
/* The claimed counterpart. Same footnote language as the unclaimed strip below —
   quiet left rule, muted text — and deliberately NOT steel, NOT a tick, NOT a
   badge. Claiming proves one thing (this business asked to be listed) and styling
   it as a mark of quality would smuggle in the endorsement the copy refuses to
   make. The left rule is steel-tinted rather than plain so the two strips are
   distinguishable at a glance without either one looking like a rank. */
.dir-claim--claimed {
  border-left: 2px solid var(--steel);
  background: rgba(127, 180, 216, .03);
  color: var(--muted);
  font-size: .92rem;
}
.dir-claim--claimed .pf-claim-eyebrow { color: var(--steel); }

.dir-claim--unclaimed {
  border-left: 2px solid var(--line2);
  background: rgba(255, 255, 255, .015);
  color: var(--muted);
  font-size: .92rem;
}
.dir-claim--unclaimed .pf-claim-eyebrow { color: var(--faint); }

/* The outbound link in the disclosure is evidence a reader can check, so it stays
   a link — but it is nofollow: we did not earn a vote for a page we built without
   asking, and the do-follow link is a benefit of CLAIMING (see /pros). */
.dir-claim--unclaimed a[rel~="nofollow"] { color: var(--muted); text-decoration: underline; }

/* The unclaimed chip on a directory card. Same muted treatment as the disclosure
   on the listing page, for the same reason: it is a status, not an achievement,
   and the default chip styling reads as one of the studio's credentials. */
.dir-card-chip--unclaimed { color: var(--faint); border-color: var(--line); }

/* --- editorial folds -------------------------------------------------------
   The shoot pages were a heading, a lede, chips and a grid — a phone book. These
   carry the part a scraper cannot copy: what the deliverable is, and the questions
   that predict the outcome. They need to read like prose, not like a spec table. */

.ml-editorial { max-width: 62ch; }

/* Wide pages centre their grid; the editorial reads better constrained, so it
   keeps its own measure rather than inheriting the grid's full width. */
.home-main .ml-editorial, .container .ml-editorial { margin-left: 0; }

.ed-list { list-style: none; padding: 0; margin: 1.25rem 0 0; display: flex; flex-direction: column; gap: .9rem; }
.ed-list li { color: var(--muted); line-height: 1.55; padding-left: 1rem; border-left: 2px solid var(--line2); }
.ed-list strong { display: block; color: var(--ink); font-weight: 650; margin-bottom: .15rem; }

/* The questions are the reason to read the page, so they get the accent rule
   rather than the quiet one the deliverables list uses. */
.ed-list--ask li { border-left-color: var(--steel); }

/* Price drivers are a set of named variables, not a ranked list — chips say that
   better than bullets, and they must never carry a figure. */
.ed-chips { list-style: none; padding: 0; margin: 1.25rem 0 1.5rem; display: flex; flex-wrap: wrap; gap: .5rem; }
.ed-chips li {
  font-family: var(--mono, monospace);
  font-size: .8rem;
  color: var(--muted);
  border: 1px solid var(--line2);
  border-radius: 20px;
  padding: .3rem .7rem;
}

/* The shoot-type framing, above the grid. Sized between the lede and body copy so
   it reads as the page's opening statement rather than a caption. */
.ml-intro { max-width: 62ch; color: var(--muted); font-size: 1.02rem; line-height: 1.6; margin: .75rem 0 1.5rem; }

/* Link lists in the editorial folds — cost handoffs and coverage gaps. Two columns
   on wide viewports because five short links in a single column reads as a stub. */
.ed-links { list-style: none; padding: 0; margin: 1.25rem 0 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: .5rem 1.5rem; max-width: 46rem; }
.ed-links li { border-left: 2px solid var(--line2); padding: .35rem 0 .35rem 1rem; }
.ed-links a { display: inline-flex; align-items: center; min-height: 24px; }

/* On /videographers/chicago these five links ARE the shoot-type navigation for the
   city, and 24px of them is not tappable. 44px only on small screens: on a desktop
   two-column grid it just loosens a list nobody is thumbing. */
@media (max-width: 700px) {
  .ed-links a { }

  /* The near-misses, which are the reason the probe floor had to move to 44. These
     measured 40 and 41 — close enough to look deliberate in a screenshot and short
     enough to miss with a thumb. `.dir-chip` is the browse control on every
     aggregation; the editorial buttons are the only route from a fold to .com.

     The `.btn` override is scoped to pages .net renders — `.p-profile` wraps the
     listing, the aggregations and the 404, and `.ml-hero` is the listing header.
     `.btn` itself is shared vocabulary, so widening it globally is the divergence
     one-network-three-properties exists to prevent; the markup inside these
     containers is written in apps/net/app/pages.js, so its presentation is mine.

     .com's request console is excluded on purpose and not by accident of selector:
     its chips measure 32 and its Route button 37, both of which are real, and both
     of which are theirs. The probe counts them separately and they go on shouts. */
  .dir-chip { }
  .p-profile .btn,
  .ml-hero .btn,
  .dir-claim .btn { }

  /* The shoot-type list on a listing page — "Weddings", "Corporate & events" — at
     24px. Same shape of miss as .ed-links, same fix. */
  .ml-list a { display: inline-flex; align-items: center; }
}

/* A quiet note under a fold — the "ask them, not us" line on an unclaimed listing.
   Smaller than body copy and muted, because it is a caveat rather than a claim. */
.ml-note { max-width: 62ch; color: var(--faint); font-size: .88rem; line-height: 1.5; margin: .9rem 0 0; }

/* 404 sub-headings. Smaller than a section h2 because the page is a recovery aid,
   not an article — the chips under them are the actual content. */
.dir-404-h { font-size: 1.05rem; margin: 1.75rem 0 .25rem; color: var(--muted); font-weight: 650; }

/* The 404's action buttons sat directly against the last chip row. The chips ARE
   the recovery path, so the buttons need to read as a fallback below them. */
.dir-404 .pf-actions { margin-top: 2rem; }

/* Wrapped section headings. app.css sets a 1.6 line-height, which is right for body
   copy and far too loose at 33px — a two-line h2 read as two separate headings with a
   gap between them ("A directory that says where" / "its listings came from"). .net
   sets its display type in sans and its headings run longer, so it owns this. */
.section-head h2, .ml-editorial h2 { line-height: 1.15; }
