/* ==========================================================================
   Release-state ribbons — the ONE place their look is defined.

   THREE states, two variants each:
     "In Beta Testing"  .tc-beta-ribbon / .tc-beta-corner   BETA_MODULES
     "In Development"   .tc-dev-ribbon  / .tc-dev-corner    DEV_MODULES
     "In Planning"      .tc-plan-ribbon / .tc-plan-corner   PLANNING_MODULES

   Markup:  templates/includes/beta_ribbon.html  (one include, two axes)
   Policy:  core/beta_gate.py                    (which modules are in which
                                                  release state)

   Used by THREE shells, which is why this is a static file rather than a rule
   inside any one template's <style> block:
     * templates/base.html            — the CRM shell, page-overlay variant
     * templates/parent/base_parent.html — the public site, corner variant on
                                        the module cards in parent/landing.html
     * templates/connect/base_connect.html — TechieCRM Connect's own minimal
                                        customer-facing shell, page-overlay
                                        variant, loaded only when the viewer
                                        has beta access (a customer joining a
                                        support session must never see it)

   ── Colour ──────────────────────────────────────────────────────────────
   Violet (#8A5EC2), matching the existing .tc-status-flag / .tc-addon-flag
   "release state" badges on the landing page — NOT the brand accent and NOT
   the primary blue. "In beta review" is a STATE a thing is in, the same family
   of meaning as a record status, so per docs/design/STATUS_COLOURS_AND_BRANDING.md
   it is deliberately exempt from tenant branding: a workspace whose brand is
   violet must not have every module look like it is in beta, and one whose
   brand is green must not have beta look released.

   ── Colour: "In Development" ────────────────────────────────────────────
   Amber/bronze (#8A5A00). Chosen against the alternatives rather than picked:
   blue and green are both taken by "action" (--tc-primary is #0078D7 in the
   CRM shell and #0C8847 on the public site), red and red-orange read as
   ERROR, and teal is a green-ish hue sitting next to a green brand.

   Amber also survives the test that matters. Violet occupies the blue
   channel; amber occupies red + green. Under deuteranopia and protanopia — the
   common forms — violet renders blue-grey and amber renders yellow-ochre,
   which is the most robust pair available. Under tritanopia both drift toward
   pink, so the design does not rely on hue alone: the two bands differ in
   LIGHTNESS as well, and stay separable in greyscale.

   Contrast, MEASURED (WCAG relative luminance, white ink, composited):

     beta  #8A5EC2 a.62 over white -> #B69BD9   2.42:1   (existing, normal)
     beta  #8A5EC2 a.92 over white -> #936BC7   4.06:1   (existing, hover)
     dev   #8A5A00 a.88 over white -> #986E1F   4.58:1
     dev   #8A5A00 a.88 over #16181A -> #7C5203 6.85:1
     dev   #8A5A00 solid                        5.93:1   (hover)

   ── Colour: "In Planning" ───────────────────────────────────────────────
   Desaturated blue-grey slate (#44505D at .90). "In planning" has to read as
   FURTHER AWAY and MORE INERT than "in development", and the thing that
   carries that is CHROMA, not lightness — see the constraint below.

   Measured chroma of the composited band on a white page, (max-min)/255:

     beta  #B69BD9   .243
     dev   #986E1F   .475      warm, saturated  -> advances, asks for attention
     plan  #57626D   .086      cool, near-grey  -> recedes

   So the planning band is 5.5x less saturated than the development band and
   sits on the cool side of neutral. It is NOT a flat grey: a flat grey band
   would read as *disabled* (and disabled, on this platform, is light-grey ink
   at low contrast — the opposite of a crisp white-on-slate label). It is not
   red or red-orange, so it cannot read as an error.

   ⚠ It also had to clear the public site's OWN definition of "not blue".
   `core/tests_no_blue_public_site.py` treats hue 185-260 with HLS saturation
   above 18 as blue (Shannon, 2026-08-27: blue is not an accent colour there).
   A first pick of #33475C measured hue 209 / sat 29 — squarely blue by that
   rule, and it tripped the guard the moment the colour was written into
   landing.html. #44505D is hue 211 / **sat 15.5**, comfortably under the
   threshold, which is precisely what "desaturated blue-grey" has to mean on
   this site. `core/tests_planning_modules.py` re-checks it against the same
   threshold, so the stylesheet cannot drift blue where the guard cannot see.

   ⚠ It could NOT be made lighter, and that is worth writing down because the
   instinct is that "further away" = "paler". White ink at AA on a WHITE page
   caps the composited band's relative luminance at ~0.184, and the development
   amber already sits at 0.179 — i.e. amber is as light as an AA-passing band
   with white ink can be. Anything paler fails legibility. Recession therefore
   had to come from chroma and hue temperature, and the band is DARKER than
   amber (0.115), which also keeps the two separable in greyscale.

   Contrast, MEASURED, same method:

     plan  #44505D a.90 over white -> #57626D   6.23:1
     plan  #44505D a.90 over #16181A -> #3F4A56  9.03:1
     plan  #44505D solid                        8.23:1   (hover)

   Greyscale separation of the composited bands on white (relative luminance):
   beta 0.384, dev 0.179, plan 0.119 — every neighbouring pair differs by more
   than 0.05, so the three stay distinguishable with hue removed entirely.

   ⚠ .tc-plan-ribbon (the page-overlay variant) has NO CALLER today, on
   purpose: `PLANNING_MODULES` has no page to overlay. It is defined anyway so
   that `{% include 'includes/beta_ribbon.html' with state='plan' %}` on a
   future planning page cannot silently fall through to the BETA band — a
   mislabelled release state is worse than twenty lines of CSS.
   `core/tests_planning_modules.py` asserts both halves of that: the class is
   defined, and nothing includes the overlay variant yet.

   ⚠ The alpha is .88 and NOT the .82 the build plan proposed. .82 measures
   4.04:1 over white, not the 4.06 the plan computed and, either way, short of
   the 4.5:1 an 11.5px bold label needs. .88 clears 4.5:1 on BOTH grounds and
   still lets the page read through. The higher alpha than beta is deliberate
   twice over: "in development" is a stronger claim, and unlike a beta module
   there is nothing underneath the ribbon worth reading through.

   Both --tc-dev-band tokens are declared in the bare :root and in NO theme
   block, exactly as --tc-beta-band is. That is what makes them immune to the
   three-theme-state trap (a token defined only inside a themed block never
   applies in the unstamped "system" state): the band is theme-independent, and
   the figures above show white ink clears 4.5:1 on both grounds. Status
   colours are exempt from tenant branding for the same reason beta is — a
   release state is a state a thing is IN, not decoration.

   ── Both variants are DECORATION ────────────────────────────────────────
   pointer-events:none everywhere, so a ribbon can never eat a click on the
   control underneath it, and aria-hidden in the markup so a screen reader is
   not told "In Beta Testing" in the middle of a table. A user who is actually
   refused reads it in words on parent/beta_required.html.
   ========================================================================== */

:root {
    --tc-beta-ink: #ffffff;
    --tc-beta-band: rgba(138, 94, 194, .62);   /* semi-transparent, on purpose:
                                                  the page underneath must stay
                                                  readable through it */
    --tc-beta-band-solid: rgba(138, 94, 194, .92);

    --tc-dev-ink: #ffffff;
    --tc-dev-band: rgba(138, 90, 0, .88);      /* amber/bronze #8A5A00 — see the
                                                  measured figures above */
    --tc-dev-band-solid: rgba(138, 90, 0, 1);

    --tc-plan-ink: #ffffff;
    --tc-plan-band: rgba(68, 80, 93, .90);     /* slate #44505D — see the
                                                  measured figures above */
    --tc-plan-band-solid: rgba(68, 80, 93, 1);
}

/* ── Page overlay ───────────────────────────────────────────────────────────
   Anchored to the VIEWPORT's bottom-right corner rather than the top, because
   the top-right of the CRM shell is the user menu and the notification bell.
   z-index 850 is below every interactive layer in the measured census at the
   top of static/css/tcrm-menu.css (rail 900, sidebar 990, ribbon/header 1000,
   dialogs 2100, context menu 2200) — a watermark must never be the thing in
   front. */
.tc-beta-ribbon {
    position: fixed;
    right: -58px;
    bottom: 34px;
    z-index: 850;
    pointer-events: none;
    transform: rotate(-45deg);
    transform-origin: center;
    background: var(--tc-beta-band);
    color: var(--tc-beta-ink);
    padding: 5px 62px;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    text-align: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
    user-select: none;
}

/* Print: a watermark rotated across the corner of a printed record is noise. */
@media print {
    .tc-beta-ribbon { display: none; }
}

/* Narrow screens: the band would cross a third of the viewport. Keep it, make
   it small, and pull it clear of a bottom navigation bar. */
@media (max-width: 576px) {
    .tc-beta-ribbon {
        right: -66px;
        bottom: 26px;
        padding: 4px 58px;
        font-size: .62rem;
        letter-spacing: .08em;
    }
}

/* ── Card corner ────────────────────────────────────────────────────────────
   Clips a diagonal band across the top-right corner of the card it sits in.
   The OUTER span is the clipping square (overflow:hidden); the INNER span is
   the rotated band. Two elements, because a single rotated element cannot be
   clipped to its own parent's corner without also clipping its text.

   ⚠ Needs the card to be position:relative. Both users of this variant are:
   #features .tc-card and #deploy .tc-card in parent/landing.html already are
   (they carry an absolutely positioned ::after). */
.tc-beta-corner {
    position: absolute;
    top: 0;
    right: 0;
    width: 128px;
    height: 128px;
    overflow: hidden;
    pointer-events: none;
    border-top-right-radius: inherit;
    z-index: 2;
}

.tc-beta-corner > span {
    position: absolute;
    display: block;
    width: 190px;
    top: 26px;
    right: -50px;
    transform: rotate(45deg);
    background: var(--tc-beta-band);
    color: var(--tc-beta-ink);
    padding: 4px 0;
    font-size: .58rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-align: center;
    box-shadow: 0 1px 6px rgba(0, 0, 0, .16);
    user-select: none;
}

/* A card the user is hovering/reading: firm the band up so it reads as a
   deliberate label rather than a rendering artefact. */
.tc-card:hover > .tc-beta-corner > span,
.tc-card.open > .tc-beta-corner > span {
    background: var(--tc-beta-band-solid);
}


/* ── "In Development": the same two variants, the other colour ──────────────
   Deliberately a full copy of the geometry rather than a shared base class
   plus a colour modifier. The two ribbons are ONE decision apart today, but
   they are different claims: if "in development" ever needs a different size,
   position or wording treatment, a shared geometry class would have to be
   forked under pressure. The rules below are asserted to stay in step by
   core/tests_dev_modules.py::TheDevRibbonMirrorsTheBetaRibbon. */
.tc-dev-ribbon {
    position: fixed;
    right: -58px;
    bottom: 34px;
    z-index: 850;
    pointer-events: none;
    transform: rotate(-45deg);
    transform-origin: center;
    background: var(--tc-dev-band);
    color: var(--tc-dev-ink);
    padding: 5px 62px;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    text-align: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
    user-select: none;
}

@media print {
    .tc-dev-ribbon { display: none; }
}

@media (max-width: 576px) {
    .tc-dev-ribbon {
        right: -66px;
        bottom: 26px;
        padding: 4px 58px;
        font-size: .62rem;
        letter-spacing: .08em;
    }
}

.tc-dev-corner {
    position: absolute;
    top: 0;
    right: 0;
    width: 128px;
    height: 128px;
    overflow: hidden;
    pointer-events: none;
    border-top-right-radius: inherit;
    z-index: 2;
}

.tc-dev-corner > span {
    position: absolute;
    display: block;
    width: 190px;
    top: 26px;
    right: -50px;
    transform: rotate(45deg);
    background: var(--tc-dev-band);
    color: var(--tc-dev-ink);
    padding: 4px 0;
    font-size: .58rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-align: center;
    box-shadow: 0 1px 6px rgba(0, 0, 0, .16);
    user-select: none;
}

.tc-card:hover > .tc-dev-corner > span,
.tc-card.open > .tc-dev-corner > span {
    background: var(--tc-dev-band-solid);
}


/* ── "In Planning": the same two variants, the third colour ─────────────────
   A full copy of the geometry again, for the reason given above the "In
   Development" block: these are different CLAIMS that happen to share a shape
   today. `core/tests_planning_modules.py::ThePlanRibbonMirrorsTheOthers`
   asserts they stay in step until somebody decides otherwise. */
.tc-plan-ribbon {
    position: fixed;
    right: -58px;
    bottom: 34px;
    z-index: 850;
    pointer-events: none;
    transform: rotate(-45deg);
    transform-origin: center;
    background: var(--tc-plan-band);
    color: var(--tc-plan-ink);
    padding: 5px 62px;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    text-align: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
    user-select: none;
}

@media print {
    .tc-plan-ribbon { display: none; }
}

@media (max-width: 576px) {
    .tc-plan-ribbon {
        right: -66px;
        bottom: 26px;
        padding: 4px 58px;
        font-size: .62rem;
        letter-spacing: .08em;
    }
}

.tc-plan-corner {
    position: absolute;
    top: 0;
    right: 0;
    width: 128px;
    height: 128px;
    overflow: hidden;
    pointer-events: none;
    border-top-right-radius: inherit;
    z-index: 2;
}

.tc-plan-corner > span {
    position: absolute;
    display: block;
    width: 190px;
    top: 26px;
    right: -50px;
    transform: rotate(45deg);
    background: var(--tc-plan-band);
    color: var(--tc-plan-ink);
    padding: 4px 0;
    font-size: .58rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-align: center;
    box-shadow: 0 1px 6px rgba(0, 0, 0, .16);
    user-select: none;
}

.tc-card:hover > .tc-plan-corner > span,
.tc-card.open > .tc-plan-corner > span {
    background: var(--tc-plan-band-solid);
}
