/*
 * Styles for the SocialContent detail page (header, media gallery, payload
 * viewer). Filament only loads its own CSS bundle and does NOT scan our
 * custom Blade views, so Tailwind utility classes used there produce no CSS
 * (icons rendered at intrinsic size, gallery not gridded). We ship explicit
 * classes here instead, registered via FilamentAsset.
 *
 * COLOUR RULE (#124): a hex literal may only appear where it *defines* a custom
 * property. Everywhere else, colour comes from a token — the DS semantic roles
 * (`--tew-color-*`, which remap themselves under `.dark`) or one of the local
 * palettes declared below. A `CssTokensTest` fails the build on any stray hex.
 */

/* ------------------------------------------------------------------
   Local palettes: colour that is NOT the design system's to own.

   Both of these are Argos-specific and have no second consumer, so they are
   named here rather than pushed into the shared DS (same call we made for the
   chart palette's domain colours: the DS carries what every TEW product needs).

   1. PLATFORM colours are the *external* brands' identities (Meta's blue is
      Meta's, not ours). They are deliberately outside the DS ramp.
   2. JSON SYNTAX colours are mode-aware, and they have to be: none of the
      DS chart slots clears 4.5:1 on BOTH surfaces, because that scale is
      validated for chart *marks* (a 3:1 non-text floor). As text they would
      have failed. Each value below is measured against the surface it sits on
      (`--tew-color-bg-subtle`: #F7F9FA light, #11202A dark) and clears AA.
      Hue alone separates them, which is fine here and would not be in a chart:
      JSON is redundantly encoded — quotes mark strings, position marks keys,
      `true`/`false` are words. Colour reinforces; it never carries the meaning.
   ------------------------------------------------------------------ */
:root {
    --ssmt-platform-instagram: #e4405f;
    --ssmt-platform-facebook: #1877f2;
    --ssmt-platform-youtube: #ff0000;
    --ssmt-platform-linkedin: #0a66c2;
    --ssmt-platform-google: #4285f4;
    /* Meta (#1108). Simple Icons' own value for the brand, which is where the
       five above come from too — cross-checked by their Facebook entry still
       reading 1877F2, exactly the token on the line above.
       ⚠️ 4.96:1 light, 3.17:1 dark — clears the 3:1 non-text floor in both.
       🚨 An earlier version of this comment called it «the tightest of the
       six», which is FALSE and was published before being re-derived:
       `--ssmt-platform-linkedin` #0a66c2 is 2.92:1 on the dark surface and is
       already UNDER the floor, worse than Meta everywhere. That is a
       pre-existing defect, not one this change introduced, and it has an
       issue of its own — but the sentence written to warn people pointed at
       the wrong token and implied all six passed. */
    --ssmt-platform-meta: #0467df;

    /* TikTok (#1114). Simple Icons gives the brand `#000000`, and that is the
       reason this token did not exist: measured 2026-09-22, pure black is
       1.26:1 on the dark surface — invisible, not merely dim. So the value is
       TikTok's other brand colour, the `#25F4EE` cyan, darkened until it fits
       the window where ONE value clears the 3:1 non-text floor on both
       surfaces (relative luminance between 0.140 and 0.281).
       ⚠️ 4.59:1 light, 3.43:1 dark.

       🚨 Its absence was not an oversight, and that is why it is being filled
       rather than exempted: while `tiktok` and `tiktok_ads` drew no colour,
       «every platform has a colour rule» was a FALSE invariant, and a test
       asserting it would have been red at birth for a correct reason. The
       choice was a test with a list of exemptions — one line away from
       silencing a real omission — or removing the exemption. This is the
       second. */
    --ssmt-platform-tiktok: #0b7f7a;

    --ssmt-json-key: #7b4fc0; /* 5.34:1 */
    --ssmt-json-string: #3f7a1f; /* 4.95:1 */
    --ssmt-json-number: #0a6fa0; /* 5.24:1 */
    --ssmt-json-boolean: #9a5a12; /* 5.17:1 */
}

.dark {
    --ssmt-json-key: #c4a2f0; /* 7.73:1 */
    --ssmt-json-string: #8dc95f; /* 8.43:1 */
    --ssmt-json-number: #5fbfe6; /* 7.98:1 */
    --ssmt-json-boolean: #f0b860; /* 9.28:1 */
}

/* --- social icon (size comes from SVG width/height attrs; colour here) --- */
.ssmt-icon {
    display: inline-flex;
    line-height: 0;
    /* The containing block for the paid badge below. Harmless on every other
       icon: nothing else inside .ssmt-icon is positioned. */
    position: relative;
}

/* Most paid platforms draw their brand's glyph — linkedin_ads renders the
   LinkedIn mark — so the icon alone is ambiguous for four of the nine
   platforms (#796; it was six before #1108 gave meta_ads a mark of its own).
   The badge is the only thing that separates them at a glance, and it is
   stamped on every paid platform wherever one is drawn — tables, lists, the
   detail header (#1135) — so a platform looks the same on every page.

   ⚠️ With one exception, and it is worth naming rather than letting the
   sentence above cover it: platform_id is nullable on social_contents,
   apify_runs and apify_requests, and a row without one draws the grey globe
   with no mark, no colour and no badge — a paid platform that has lost its
   FK is indistinguishable from an unknown organic one. It is at least NAMED:
   both callers fall back to platform.unknown, because the previous fallback
   (`?? $record->platform`) was an accessor over the very relation that is
   missing, so it returned null in the one case it was written for. The
   backfill closed the FK gap in practice; nothing keeps it closed.

   ⚠️ Deliberately NOT a colour variant of the same glyph: that is the one
   candidate that fails for a colour-blind reader and washes out in dark mode,
   and it is the one the issue calls weakest. A mark with a shape and a word
   survives both.

   ⚠️ `em` here tracks the TEXT, not the icon — an earlier version of this
   comment claimed the icon and was wrong. The glyph's size is an SVG width
   attribute in pixels (`:size="20"` in the table, 24 in the detail header),
   so nothing in CSS scales with it and a caller at a much larger size would
   get this same badge. Text is the right thing to track anyway — 1.4.4 asks
   the badge to grow when the reader enlarges text — but the glyph staying
   frozen while it does is a property of the component, not of this rule.

   🚨 **This rule has a twin, and nothing links them but these two comments.**
   `.ssmt-brand__version` in `panel-marks.css` (#1129) stamps the release on the
   admin product mark and copies eight of these declarations verbatim — pill,
   ring, muted background, weight, tracking. If you restyle the badge here, go
   and do it there too; no test reads CSS, so the drift is silent. The reason
   they were not extracted, and the trigger that should extract them, are
   written at that end. */
.ssmt-icon__ads {
    position: absolute;
    right: -1.75em;
    bottom: -0.6em;
    border-radius: 0.35em;
    background: var(--tew-color-text-muted);
    color: var(--tew-color-bg);
    padding: 0 0.25em;
    font-size: 0.5em;
    font-weight: 700;
    line-height: 1.5;
    letter-spacing: 0.02em;
    /* The glyph underneath is a solid brand colour; without a ring the badge
       reads as part of it rather than on top of it. */
    box-shadow: 0 0 0 0.12em var(--tew-color-bg);
}

/* platform-icon table cell: the column is centered (->alignCenter()), but for
   a ViewColumn Filament puts `fi-align-center` on the <td>, not on the inner
   `.fi-ta-col` flex wrapper (which stays `justify-start`), so the icon would
   sit left. Grow this span to fill the wrapper and center its own content. */
.ssmt-platform-cell {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: center;
}

/* next-refresh table cell: same ViewColumn alignment issue as the platform cell
   (the `.fi-ta-col` flex wrapper stays justify-start). Centre the date badge /
   pause icon by growing to fill the wrapper. */
.ssmt-cell-center {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: center;
}
.ssmt-cell-end {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: flex-end;
}

/* Count-column hover popover (B4b — Clienti brands/users, Utenti clients),
   rendered by lara-zeus/popover. The plugin ships no CSS and our custom Filament
   theme doesn't scan its vendor Blade, so none of the utilities in its view get
   compiled — we must supply every visual property here.

   The floating panel: `z-50` (else sibling table cells paint over it), the
   surface (`bg-white dark:bg-gray-800 ring rounded shadow`) and a content-driven
   width in place of the uncompiled `w-[…px]`. */
/* The DS semantic roles remap themselves under `.dark`, so the light/dark pair
   collapses into one rule. */
.fi-popover-content {
    z-index: 60;
    width: auto;
    min-width: 11rem;
    max-width: 20rem;
    background: var(--tew-color-surface);
    color: var(--tew-color-text);
    border: 1px solid var(--tew-color-border);
    border-radius: var(--tew-radius-md);
    box-shadow: var(--tew-shadow-md);
}

/* In-table trigger: the plugin wraps the cell in its own `grid px-3 py-4 gap-y-1`,
   which double-pads the (already padded) cell — taller row + the number indented
   out of line with the column header. Strip that padding and right-align the
   trigger so the count sits exactly like a normal ->alignEnd() numeric column. */
.fi-popover.fi-ta-text {
    padding: 0;
    row-gap: 0;
}
.fi-popover.fi-ta-text .fi-popover-trigger {
    justify-content: flex-end;
}

.ssmt-poplist {
    margin: 0;
    padding: 4px 0;
    list-style: none;
    max-height: 18rem;
    overflow-y: auto;
    text-align: left;
}
.ssmt-poplist li {
    padding: 4px 12px;
    white-space: nowrap;
}
.ssmt-poplist a {
    display: block;
    color: inherit;
    text-decoration: none;
}
.ssmt-poplist a:hover {
    text-decoration: underline;
}
.ssmt-poplist__more {
    font-size: 0.8rem;
    opacity: 0.55;
}
.ssmt-poplist__all {
    margin-top: 4px;
    padding-top: 8px;
    border-top: 1px solid var(--tew-color-border);
}
.ssmt-icon--instagram {
    color: var(--ssmt-platform-instagram);
}
.ssmt-icon--facebook {
    color: var(--ssmt-platform-facebook);
}
.ssmt-icon--youtube {
    color: var(--ssmt-platform-youtube);
}
.ssmt-icon--linkedin {
    color: var(--ssmt-platform-linkedin);
}
.ssmt-icon--google {
    color: var(--ssmt-platform-google);
}
/* Without this the Meta glyph renders in the inherited text colour, and
   `meta_ads` used to be coloured — it drew Facebook's glyph and picked up
   Facebook's rule, so #1108 would have taken a colour away. */
.ssmt-icon--meta {
    color: var(--ssmt-platform-meta);
}
/* The seventh and last slug, added by #1114 — `tiktok` and `tiktok_ads` both
   draw `si-tiktok`. Until it existed this list covered 6 of the 7 slugs
   `<x-social-icon>` can render, and nothing said so: a grey mark among
   coloured ones looks like a rendering glitch, not like a missing line.
   `PlatformSatelliteTablesTest` now presides over the list in both
   directions, which is only possible because there is no longer a platform
   that is uncoloured on purpose. */
.ssmt-icon--tiktok {
    color: var(--ssmt-platform-tiktok);
}

/* --- detail header --- */
.ssmt-content-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
}
.ssmt-content-header__left {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}
.ssmt-content-header__logo {
    width: 1.5rem;
    height: 1.5rem;
    flex-shrink: 0;
    border-radius: 0.25rem;
    object-fit: contain;
}
.ssmt-content-header__brand {
    font-size: 0.875rem;
    font-weight: 400;
    color: var(--tew-color-text-subtle);
}
.ssmt-content-header__icon {
    flex-shrink: 0;
    line-height: 0;
}

/* --- media gallery --- */
.ssmt-gallery__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.5rem;
}
@media (min-width: 640px) {
    .ssmt-gallery__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}
@media (min-width: 768px) {
    .ssmt-gallery__grid {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }
}
.ssmt-gallery__item {
    position: relative;
    display: block;
    aspect-ratio: var(--tew-media-ratio-square);
    overflow: hidden;
    border-radius: var(--tew-media-tile-radius);
    background: var(--tew-media-tile-placeholder);
    box-shadow: var(--tew-media-tile-shadow);
    transition: opacity var(--tew-dur-fast) var(--tew-ease-out);
}
.ssmt-gallery__item:hover {
    opacity: var(--tew-media-tile-hover-opacity);
}
.ssmt-gallery__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.ssmt-gallery__overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ssmt-gallery__overlay img {
    position: absolute;
    inset: 0;
    opacity: 0.6;
}
.ssmt-gallery__overlay svg {
    position: relative;
    width: 2.25rem;
    height: 2.25rem;
    color: var(--tew-color-text-on-dark);
    z-index: 1;
}
/* Media-type scrims. All three carry a white glyph, so each must clear 3:1
   against white (non-text graphic) — they do, comfortably.
   ⚠️ They are OPAQUE colours, not veils: a scrim goes UNDER the thumbnail,
   which sits on it at 60%. Laid over it, it hides it — the analysis box did,
   and showed every video as a black square (#1300).
   The document tile used to be RED. It is a media type, not a warning, and in
   this system red means danger: a PDF thumbnail was telling the reader
   something had gone wrong. It now uses the DS ink navy, and the glyph — not
   the colour — says which type it is.

   These three values are no longer ours: the design system ships them as
   `--tew-media-scrim-*` since v1.5.0, authored FROM this file and from
   app-social-scraper's gallery, because two apps had improvised the same
   treatment. The rule above is encoded there too, so adopting the tokens does
   not reintroduce the red (#190). */
.ssmt-gallery__overlay--video {
    background: var(--tew-media-scrim-video);
}
.ssmt-gallery__overlay--audio {
    background: var(--tew-media-scrim-audio);
}
.ssmt-gallery__overlay--document {
    background: var(--tew-media-scrim-document);
}

/* --- creative analysis, one block per media (#1259) ---
   The thumbnail beside the words about it, numbered as in the post and opening
   the media. Sizes in rem, never px, so the block grows with the text (WCAG
   1.4.4 / 1.4.12); the text column wraps under the thumbnail on narrow screens. */
.ssmt-analysis-media {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.ssmt-analysis-media__meta {
    font-size: 0.75rem;
    color: var(--tew-color-text-subtle);
}
.ssmt-analysis-media__item {
    display: grid;
    grid-template-columns: 6rem minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}
.ssmt-analysis-media__item + .ssmt-analysis-media__item {
    padding-top: 1rem;
    border-top: 1px solid var(--tew-color-border);
}
@media (max-width: 30rem) {
    .ssmt-analysis-media__item {
        grid-template-columns: minmax(0, 1fr);
    }
}
/* The media gallery's tile (.ssmt-gallery__item), at a fixed width — and a
   <button>, so the browser's button chrome goes. */
.ssmt-analysis-media__thumb {
    width: 6rem;
    padding: 0;
    border: 0;
    cursor: pointer;
}
.ssmt-analysis-media__thumb:focus-visible {
    outline: none;
    box-shadow: var(--tew-shadow-focus);
}
/* The number sits on the image, so it carries its own dark plate: the
   document tiles' scrim, which clears 4.5:1 under white text. */
.ssmt-analysis-media__position {
    position: absolute;
    left: 0.25rem;
    bottom: 0.25rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--tew-radius-sm);
    background: var(--tew-media-scrim-document);
    color: var(--tew-color-text-on-dark);
    font-size: 0.75rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.ssmt-analysis-media__text {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 0;
}
.ssmt-analysis-media__text dt {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--tew-color-text);
}
.ssmt-analysis-media__text dd {
    margin: 0.25rem 0 0;
    font-size: 0.875rem;
    color: var(--tew-color-text-muted);
}
.ssmt-analysis-media__none {
    color: var(--tew-color-text-subtle);
}

/* --- GLightbox overrides ---
   Filament/Tailwind's base reset (img { max-width:100%; height:auto }) fights
   GLightbox's inline px sizing on the slide image, leaving an overflow
   scrollbar. Force the image to fit the slide and clip any overflow. */
.glightbox-container .gslide-media {
    overflow: hidden;
    box-shadow: none;
}
.glightbox-container .gslide-image img {
    max-width: 100%;
    max-height: 90vh;
    width: auto !important;
    height: auto !important;
    object-fit: contain;
}
/* Videos play through Plyr (bundled with GLightbox). Plyr locks the wrapper
   to a fixed 16:9 ratio (`.plyr__video-wrapper--fixed-ratio`), which boxes
   vertical (9:16) ad creatives into a short, wide frame with empty space
   around them. Drop the fixed ratio and let the <video> flow at its own
   aspect ratio (it is normally position:absolute inside the wrapper), bounded
   to the viewport, so the player hugs the clip whatever its shape. */
.glightbox-container .gslide-video,
.glightbox-container .gslide-video .gvideo-wrapper,
.glightbox-container .gslide-video .plyr {
    width: auto !important;
    height: auto !important;
    max-width: 90vw !important;
    background: transparent !important;
    box-shadow: none !important;
}
.glightbox-container .gslide-video .plyr__video-wrapper--fixed-ratio {
    aspect-ratio: auto !important;
    padding-bottom: 0 !important;
    height: auto !important;
    width: auto !important;
    background: transparent !important;
}
.glightbox-container .gslide-video .plyr__video-wrapper video {
    position: relative !important;
    width: auto !important;
    height: auto !important;
    max-width: 90vw !important;
    max-height: 85vh !important;
    object-fit: contain;
    background: var(--tew-media-scrim-video);
}

/* --- payload viewer toolbar (expand all / collapse all / copy) ---
   One class for all three: they are the same control in the same strip and
   they change for the same reason, so a second rule for the copy button
   would be the same look written twice. */

.ssmt-payload__bar {
    display: flex;
    justify-content: flex-end;
    gap: 0.25rem;
    margin-bottom: 0.5rem;
}
.ssmt-payload__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    border-radius: var(--tew-radius-md);
    background: var(--tew-color-bg-muted);
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--tew-color-text-muted);
    cursor: pointer;
    border: 0;
}
.ssmt-payload__btn:hover {
    background: var(--tew-color-border);
}
.ssmt-payload__btn:focus-visible {
    outline: none;
    box-shadow: var(--tew-shadow-focus);
}
/* rem, not px: an icon frozen in pixels cannot grow with the text around it,
   and 1.4.4 Resize Text asks it to (accessibility §3). */
.ssmt-payload__btn-icon {
    width: 1rem;
    height: 1rem;
}
/* --- JSON CodeEditor (App\Filament\Support\JsonFieldSchema) ---
   Real CSS, not Tailwind arbitrary variants written in PHP: those compiled
   into a bundle the panel does not load, so the "expand to full screen" modal
   rendered at the same height as the field it expanded. Why, and the
   measurement, are in that class's docblock — this file ships to every admin
   page, and the explanation does not need to. */
.ssmt-json-editor .cm-editor {
    min-height: 8rem;
    max-height: 18rem;
}
.ssmt-json-editor--modal .cm-editor {
    min-height: 60vh;
    max-height: 80vh;
}

/* --- JSON tree --- */
/*
 * The line that says how much of a dataset is on screen (#852 §7).
 *
 * ⚠️ No fixed height and no px font size: `accessibility` §3 — a box frozen in
 * pixels cannot absorb text at 200%, and this one carries the sentence a
 * reader most needs to be able to enlarge.
 */
.ssmt-payload__note {
    margin-bottom: 0.5rem;
    font-size: 0.75rem;
    color: var(--tew-color-text-muted);
}
.ssmt-payload__note-source {
    margin-inline-start: 0.375rem;
    opacity: 0.85;
    font-style: italic;
}

/*
 * 🚨 The box is focusable since #852 §7 (`scrollable-region-focusable`), so it
 * needs a focus ring — a control you can tab to and cannot see is 2.4.7 traded
 * for 2.1.1. `:focus-visible` and not `:focus`, so a mouse click on the JSON
 * does not draw one.
 */
.ssmt-jt__wrap:focus-visible {
    outline: 2px solid var(--tew-color-focus, currentColor);
    outline-offset: 2px;
}
.ssmt-jt__wrap {
    max-height: 24rem;
    overflow: auto;
    border-radius: var(--tew-radius-md);
    background: var(--tew-color-bg-subtle);
    padding: 0.75rem;
    font-size: 0.75rem;
    font-family: var(--tew-font-mono);
    line-height: 1.6;
}
.ssmt-jt__node {
    border-left: 2px solid var(--tew-color-border);
    padding-left: 0.5rem;
    margin: 0;
}
.ssmt-jt__node > summary {
    list-style: none;
    cursor: pointer;
    user-select: none;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    color: var(--tew-color-text-subtle);
}
.ssmt-jt__node > summary:focus-visible {
    outline: none;
    box-shadow: var(--tew-shadow-focus);
    border-radius: var(--tew-radius-sm);
}
.ssmt-jt__node > summary::-webkit-details-marker {
    display: none;
}
.ssmt-jt__node > summary::before {
    content: '▶';
    font-size: 0.55rem;
    color: var(--tew-color-text-subtle);
    display: inline-block;
    width: 0.8rem;
    flex-shrink: 0;
    transition: transform 0.1s ease;
}
.ssmt-jt__node[open] > summary::before {
    transform: rotate(90deg);
}
.ssmt-jt__children {
    padding-left: 1.25rem;
}
.ssmt-jt__row {
    padding: 0.05rem 0;
}
.ssmt-jt__key {
    color: var(--ssmt-json-key);
}
.ssmt-jt__str {
    color: var(--ssmt-json-string);
    word-break: break-all;
}
.ssmt-jt__num {
    color: var(--ssmt-json-number);
}
.ssmt-jt__bool {
    color: var(--ssmt-json-boolean);
}
.ssmt-jt__null {
    color: var(--tew-color-text-subtle);
    font-style: italic;
}
.ssmt-jt__empty {
    color: var(--tew-color-text-subtle);
}
.ssmt-jt__bracket {
    color: var(--tew-color-text-muted);
    font-weight: 600;
}
.ssmt-jt__count {
    font-size: 0.65rem;
    color: var(--tew-color-text-subtle);
    font-weight: normal;
    padding: 0 0.2rem;
}
.ssmt-jt__colon {
    color: var(--tew-color-text-muted);
}
.ssmt-jt__scalar {
    font-size: 0.875rem;
    color: var(--tew-color-text-muted);
}
.ssmt-jt__placeholder {
    font-size: 0.875rem;
    color: var(--tew-color-text-subtle);
}

/* No `.dark` block below this line, and that is the point: every colour above is
   a semantic DS role or a local token that already declares its own dark value,
   so dark mode needs no second copy of the stylesheet. The thirteen dark
   overrides this file used to carry were thirteen chances to drift. */

/* ------------------------------------------------------------------
   Personalisation macro badge (#757).

   LinkedIn's `%FIRSTNAME%` reaches us inside real ad copy, and printing it
   raw reads as unresolved output to an agency account. `PersonalisationMacro`
   swaps it for a badge saying the field's name; the chrome here is what makes
   it legible AS a stand-in — «nome» set in running text with no box would
   just look like a typo.

   ⚠️ COLOUR: this is a FILLED surface, so it takes a `*-solid` role and its
   declared label — the one pairing the DS guarantees clears 4.5:1 against
   itself (`tokens.json` §product layer). The obvious-looking choice was
   `info-text` on `info-bg`, and it is wrong: the `*-text` roles are measured
   against `bg`/`surface`, not against a tinted fill. Measured in the browser
   before this was written — #0A78AE on #E8F5FB is **4.38:1**, under the floor
   for text this size; #FFFFFF on #0B5E87 is **7.08:1**, and both tokens hold
   the same value in dark mode, so there is no second measurement to get wrong.

   Everything is sized in `em` — the badge rides the caption's own type
   (a11y 1.4.4/1.4.12: a box frozen in px cannot absorb text at 200%).
   ------------------------------------------------------------------ */
.ssmt-macro {
    display: inline;
    padding-inline: 0.45em;
    padding-block: 0.1em;
    border-radius: 0.35em;
    /* The EDGE, which is a separate measurement from the label. The fill is
       7.08:1 against a white card and only 1.86:1 against the dark one, so in
       dark mode the chip would melt into the surface — «evident» has to hold
       in both. `info` is the non-text role and clears the 3:1 floor on both
       surfaces (3.74:1 light, 4.73:1 dark, measured in the browser). */
    border: 1px solid var(--tew-color-info);
    background-color: var(--tew-color-primary-solid);
    color: var(--tew-color-on-primary-solid);
    font-size: 0.85em;
    font-weight: 600;
    /* The `title` explains what the badge stands for; `help` says there is
       something to hover WITHOUT promising a click, which a solid chip in the
       brand blue could otherwise imply. */
    cursor: help;
    white-space: nowrap;
}

/* ------------------------------------------------------------------
   Mood radar (#1222): eleven axes, 0-10, drawn by MoodRadarBuilder.
   The shape is the chart palette's first colour; the two moods the
   analysis named stand out in green, dot and label alike.
   ------------------------------------------------------------------ */
.ssmt-mood-radar {
    /* A floor under the width, like the engagement charts: SVG text scales
       with the drawing, and in half a column or on a phone the labels came
       out at 7-8px (review, R4). Below the floor the radar scrolls. */
    overflow-x: auto;

    /* Green, the positive colour of the brand — the coral first tried read
       as «bad». The DS's TEXT green, not the brand green: that one is 3.5:1 on
       white, under the 4.5:1 a label needs; this one is tuned per theme. */
    --ssmt-mood-named: var(--tew-color-success-text);

    margin: 0;
}

.ssmt-mood-radar__svg {
    inline-size: 100%;
    min-inline-size: 26rem;
    max-inline-size: 34rem;
    block-size: auto;
}

.ssmt-mood-radar__ring,
.ssmt-mood-radar__spoke {
    fill: none;
    stroke: var(--tew-color-border);
    stroke-width: 1;
}

.ssmt-mood-radar__shape {
    fill: var(--tew-chart-1);
    fill-opacity: 0.25;
    stroke: var(--tew-chart-1);
    stroke-width: 2;
}

.ssmt-mood-radar__dot {
    fill: var(--tew-color-text-subtle);
}

.ssmt-mood-radar__dot--named {
    fill: var(--ssmt-mood-named);
}

.ssmt-mood-radar__label {
    font-family: var(--tew-font-sans);
    /* In viewBox units, like the engagement charts' text: 15 of 540 is about
       11.5px at the 26rem floor and 15px at the 34rem ceiling. */
    font-size: 15px;
    fill: var(--tew-color-text-muted);
}

.ssmt-mood-radar__label--named {
    font-weight: 600;
    fill: var(--ssmt-mood-named);
}

/* A link inside an entry says so on hover, like every other link: Filament
   colours it and stops there. Two shapes, because Filament renders two: the
   anchor wraps the text on a plain entry (the brand), and sits inside it on
   an entry with an icon («Apri originale»). */
a:hover > .ssmt-entry-link,
.ssmt-entry-link a:hover {
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

/* ------------------------------------------------------------------
   Search hit (#1273): the word the search box found, in the «Found in»
   column of the content lists. A marker on the text, from the DS warning
   tint, with the body text colour on it — the pairing the DS validates for
   text on its `*-bg` roles, in both modes. Weight carries it too, so the
   mark does not rest on colour alone.
   ------------------------------------------------------------------ */
.ssmt-search-hit {
    background-color: var(--tew-color-warning-bg);
    color: var(--tew-color-text);
    font-weight: 600;
    border-radius: var(--tew-radius-sm);
    padding: 0 0.125em;
}

/* The search box of the six content tables, as wide as the toolbar lets it be
   (#1310). Filament's own field, widened: its debounce, clear button, hidden
   label and Enter key come with it. Scoped by `ContentTableToolbar::CSS_CLASS`,
   so no other table changes. The «how it works» icon sits between the box and
   the filter trigger (render hook `TOOLBAR_SEARCH_AFTER`).
   ⚠️ The first rule leans on the anonymous <div> Filament wraps the search,
   filter and column triggers in: a Filament update that adds a level makes it
   match nothing, silently. The browser gate measures the width (#1310). */
.ssmt-content-table .fi-ta-header-toolbar > div:has(> .fi-ta-search-field) {
    flex: 1 1 auto;
}

.ssmt-content-table .fi-ta-search-field {
    flex: 1 1 auto;
}

/* The «Meaning» mode (#1274): the question field takes the box's place, and the
   box stays in the DOM, hidden, so Filament's own markup is left alone. */
.ssmt-content-table[data-search-mode='meaning'] .fi-ta-search-field {
    display: none;
}

.ssmt-content-table .fi-ta-header-toolbar > div:has(> .ssmt-search-question) {
    flex: 1 1 auto;
    align-items: flex-start;
}

.ssmt-search-question {
    display: flex;
    flex: 1 1 auto;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: flex-start;
}

/* What a search costs a client on credits (#1456), on its own line under the
   field and the button. */
.ssmt-search-question-cost {
    flex-basis: 100%;
    margin: 0;
    font-size: 0.875rem;
    color: var(--tew-color-text-muted);
}

.ssmt-search-question > .fi-input-wrp {
    flex: 1 1 auto;
}

.ssmt-search-question-input {
    resize: vertical;
}

.ssmt-search-modes {
    padding: 0.5rem 1rem 0;
}

/* «Meaning» where the search was not bought (#1389): shown, and visibly not
   usable. An inactive control is outside WCAG's contrast requirement (1.4.3,
   «part of an inactive user interface component»), so the dimming is allowed;
   the reason is in its tooltip and in the sr-only text it is described by. */
.ssmt-search-modes .ssmt-search-modes-off {
    opacity: 0.55;
    cursor: not-allowed;
}

/* «These are only the closest» (#1274): design-system tokens, which carry their
   own dark values; the text in the text colour, for AA on the warning ground.
   The region around it is always there and draws nothing when empty. */
.ssmt-search-closest {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    margin: 0 1rem 0.75rem;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--tew-color-warning);
    border-radius: var(--tew-radius-sm);
    background: var(--tew-color-warning-bg);
    color: var(--tew-color-text);
}

/* The question's words the word search finds (#1354): under the notice, on the
   page's own ground — it offers a way on, it does not warn. */
.ssmt-search-words {
    margin: 0 1rem 0.75rem;
    color: var(--tew-color-text);
}

.ssmt-search-words-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.375rem;
}

.ssmt-search-closest-icon {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    color: var(--tew-color-warning);
}

.ssmt-search-help h3 {
    margin: 1rem 0 0.25rem;
    font-weight: 600;
}

.ssmt-search-help h3:first-child {
    margin-top: 0;
}

.ssmt-search-help ul {
    margin: 0.5rem 0 0;
    padding-inline-start: 1.25rem;
    list-style: disc;
}

.ssmt-search-help li + li {
    margin-top: 0.25rem;
}

.ssmt-search-help ul + p,
.ssmt-search-help p + p {
    margin-top: 0.75rem;
}

/* --- the most engaging posts, on the client dashboard (#1285) --- */
.ssmt-top-posts {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    list-style: none;
    margin: 0;
    padding: 0;
}
@media (min-width: 640px) {
    .ssmt-top-posts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (min-width: 1280px) {
    .ssmt-top-posts {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
.ssmt-top-posts__card {
    display: flex;
    gap: 0.75rem;
    height: 100%;
    padding: 0.75rem;
    border-radius: var(--tew-radius-md);
    color: inherit;
    text-decoration: none;
}
a.ssmt-top-posts__card:hover {
    background: var(--tew-color-bg-muted);
}
/* An outline, not only the background: the muted fill is about 1.1:1 against
   white, too little to say where the focus is. */
a.ssmt-top-posts__card:focus-visible {
    outline: 2px solid var(--tew-color-focus, currentColor);
    outline-offset: 2px;
}
.ssmt-top-posts__tile {
    flex: 0 0 6rem;
    align-self: flex-start;
}
.ssmt-top-posts__body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}
.ssmt-top-posts__meta {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    min-width: 0;
    font-weight: 600;
}
.ssmt-top-posts__brand,
.ssmt-top-posts__client {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ssmt-top-posts__client,
.ssmt-top-posts__date,
.ssmt-top-posts__empty {
    color: var(--tew-color-text-subtle);
    font-weight: 400;
}
.ssmt-top-posts__date {
    font-size: 0.875em;
}
.ssmt-top-posts__caption {
    overflow-wrap: anywhere;
}
.ssmt-top-posts__figures {
    display: flex;
    flex-direction: column;
    font-size: 0.875em;
}
.ssmt-top-posts__figures span {
    color: var(--tew-color-text-subtle);
}

/* ------------------------------------------------------------------
   Content lists: the preview column (#1408).

   The row must not grow. Two vertical paddings sit around the picture:
   Filament's `py-4` on the image div, and the DS density padding theme.css
   puts on the <td> of every cell without a `.fi-ta-text`. The tallest cell
   already in the row is a badge cell, 44px (the row is 45 with its border,
   measured in the browser on 2026-10-07): no inner padding, 0.25rem on the
   <td> and the 2.25rem picture set in ContentTableColumns make 44px too.

   ⚠️ Sized by measuring, not by reading Tailwind's scale: two derived
   versions grew the row, because the second padding is ours, not Filament's.

   `td.` gives the cell rule (0,2,1) over theme.css's
   `.fi-ta-cell:not(:has(.fi-ta-text))` (0,2,0): two separate assets, so the
   override must not depend on which one loads last. In rem, never px, so the
   picture grows with the badges when text is resized (accessibility, trap 3).
   ------------------------------------------------------------------ */
td.fi-ta-cell.ssmt-content-preview-cell {
    padding-block: 0.25rem;
}
.ssmt-content-preview-cell .fi-ta-image:not(.fi-inline) {
    padding-block: 0;
}
.ssmt-content-preview-cell img {
    border-radius: var(--tew-radius-sm);
}
