/* RolloTV brand layer for the Studio template - the public site (rollotv.com).
   Loaded AFTER app.min.css.

   PART 1 is copied from server/public/assets/css/brand.css, the layer the admin
   panel and the customer portal already load. It is what makes all three
   properties read as one product, so KEEP THE TWO FILES IN SYNC: if the panel's
   token block changes, change it here in the same edit.

   PART 2 is the marketing site's own additions. The panel has no hero, no
   pricing table and no legal placeholders, so those live here and only here.

   Nothing in this file restyles a Bootstrap component. Anything that looks like
   a card, a button, a badge or a table IS the template's, unmodified. */


/* ==========================================================================
   PART 1 - shared with the panels
   ========================================================================== */

/* The template ships #1f6bff as --bs-theme, and its own .theme-red (#e6180d) is
   close to the brand but not it. Brand red is #E10611. Re-pointing the variable
   rather than writing component rules means every .btn-theme / .text-theme /
   .bg-theme / spinner / progress bar picks it up unchanged. */
:root,
:root[data-bs-theme="light"],
:root[data-bs-theme="dark"],
body {
	--bs-theme: #E10611 !important;
	--bs-theme-rgb: 225, 6, 17 !important;
	--bs-theme-color: #FFFFFF !important;
	--bs-theme-color-rgb: 255, 255, 255 !important;
}

/* Page band and card fill: #F4F4F4 in place of the template's #EBEEF4
   (product owner, 2026-09-24). This is the grey behind every section that is
   not .bg-component, and the fill of every .bg-light card.

   SCOPED TO THE LIGHT SCHEME ONLY, deliberately. In the template's dark scheme
   #EBEEF4 is the TEXT colour, not a surface, so a blanket find-and-replace or a
   rule that also matched [data-bs-theme="dark"] would repaint dark-mode body
   text into a near-invisible grey. The site never sets a dark scheme today, but
   the variable block it would use is one attribute away. */
:root,
:root[data-bs-theme="light"] {
	--bs-body-bg: #F4F4F4;
	--bs-body-bg-rgb: 244, 244, 244;
	--bs-light: #F4F4F4;
	--bs-light-rgb: 244, 244, 244;
	--bs-secondary-bg: #F4F4F4;
	--bs-secondary-bg-rgb: 244, 244, 244;
	--bs-secondary-bg-subtle: #F4F4F4;
	--bs-tertiary-bg: #F4F4F4;
	--bs-tertiary-bg-rgb: 244, 244, 244;
}

/* Brand lockup: mark + wordmark. Sizing only - the template owns the typography. */
.brand-mark {
	width: 26px;
	height: 26px;
	flex: 0 0 auto;
}

.brand-mark-lg {
	width: 64px;
	height: 64px;
}

/* Global UI scale. The Studio template sets --bs-body-font-size to 0.875rem (14px)
   for dense admin tables but leaves every padding, sidebar and header dimension in
   rem against a 16px root - full-size whitespace around 87.5% text, which reads as
   a browser stuck at ~85% zoom. Scaling the root instead of the body keeps the
   template's own proportions intact and moves text AND chrome together.
   Desktop only: below 992px the template swaps to its mobile layout and the
   viewport stops having room to spend. Identical to the panel, so a visitor moving
   from rollotv.com to the portal sees no jump in scale. */
@media (min-width: 992px) {
	html {
		font-size: 112.5%;
	}
}

/* No header shadow. The template paints one as rgba(var(--bs-theme-rgb), 0.1) - a
   tint of the theme colour - which was fine at its default blue but reads as a pink
   smear under the header once --bs-theme-rgb is the brand red. */
.app-header {
	box-shadow: none;
}


/* ==========================================================================
   PART 2 - the marketing site only
   ========================================================================== */

/* ---------------------------------------------------------- hero carousel ---
   The slides carry width/height attributes so the browser reserves the right
   box before the image arrives and the hero does not shift. Those attributes
   also set a literal pixel height, which fights .w-100 and stretches the shot,
   so the height has to be released back to the aspect ratio here. */
#appShots .carousel-item img {
	height: auto;
}

/* Dots below the image, not floating over it. The template's own indicators are
   white and absolutely positioned, which put them on the light caption strip
   where they were invisible. */
#appShots .carousel-indicators {
	position: static;
	margin: .75rem 0 0;
}

#appShots .carousel-indicators [data-bs-target] {
	width: 8px;
	height: 8px;
	border: 0;
	border-radius: 50%;
	background-color: var(--bs-body-color);
	opacity: .2;
}

#appShots .carousel-indicators .active {
	background-color: var(--bs-theme);
	opacity: 1;
}

/* -------------------------------------------------------- disclaimer band ---
   The standing disclaimer on Home. A flat, full-bleed tint rather than a card:
   an alert card with a left border, a shadow and a grid of cross icons was
   tried first and read as generic boilerplate, which is the opposite of what a
   disclaimer needs to do. A band the page cannot scroll past without noticing
   does the job with less decoration. */
.disclaimer-band {
	background-color: rgba(var(--bs-theme-rgb), .06);
}

/* ------------------------------------------------------------------ chrome ---
   The template's .app-header is position:fixed and .app reserves 3.75rem for it.
   That is the whole sticky-header mechanism; the site adds only a hairline, because
   with the shadow killed above there is otherwise nothing separating a white header
   from a white first section. */
.app-header.navbar {
	border-bottom: 1px solid var(--bs-border-color);
}

/* Font Awesome selects its glyph by font-weight: the Free solid set is 900, and
   .fa sets that. But vendor.min.css loads BEFORE app.min.css, so any template
   type utility that also carries a weight wins on source order - .display-1
   through .display-6 are font-weight:300. The icon then falls back to Regular
   if the glyph exists there and to tofu if it does not, which is how fa-key on
   the Premium card rendered as an empty box while fa-circle-play beside it
   quietly turned into an outline. The template's own landing page combines
   .display-6 with <iconify-icon>, an SVG element, where this cannot happen.
   Re-asserting the weight keeps an icon an icon however it is sized. Brands
   (.fab) and the regular set (.far) carry their own weights and are untouched. */
.fa,
.fas,
.fa-solid {
	font-weight: 900;
}

/* In-page anchors (#features, #faq...) would otherwise land under the fixed header. */
[id] {
	scroll-margin-top: 4.75rem;
}

html {
	scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}
}

/* Current page in the navbar. Bootstrap's .active only recolours the link; the red
   rule underneath is what makes it readable at a glance on a light header. */
.app-header .navbar-nav .nav-link.active {
	color: var(--bs-body-color);
	font-weight: 600;
}

.app-header .navbar-nav .nav-link.active::after {
	content: "";
	display: block;
	height: 2px;
	margin-top: 2px;
	border-radius: 2px;
	background-color: var(--bs-theme);
}

/* The mobile drawer is absolutely positioned over the page, so the underline would
   sit against nothing. */
@media (max-width: 991.98px) {
	.app-header .navbar-nav .nav-link.active::after {
		display: none;
	}

	.app-header .navbar-nav .nav-link.active {
		color: var(--bs-theme);
	}
}

/* French header. The French nav labels are longer than the English ones, and
   with the language switcher the French header does not fit on one line from
   992 to 1199px: the switcher and the login button wrapped onto a second row
   over the hero. French pages therefore use .navbar-expand-xl and keep the
   drawer up to 1199.98px. The template's own drawer rule in app.min.css stops
   at 991.98px, so its declarations are repeated here for the extra range, and
   the active-link underline gives way to colour exactly as it does below 992px.
   English pages keep .navbar-expand-lg and never match these selectors. */
@media (min-width: 992px) and (max-width: 1199.98px) {
	/* 3rem, not the template's 1rem: at this width the container gutter is
	   px-lg-5 (3rem), and this keeps the links lined up under the toggler the
	   way the phone drawer does. */
	.app-header.navbar.navbar-expand-xl .navbar-collapse {
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		background: var(--bs-app-header-bg);
		padding: 0 3rem;
	}

	.app-header.navbar-expand-xl .navbar-nav .nav-link.active::after {
		display: none;
	}

	.app-header.navbar-expand-xl .navbar-nav .nav-link.active {
		color: var(--bs-theme);
	}
}

/* Keyboard skip link. Off-screen until focused. */
.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 1040;
	padding: .75rem 1.25rem;
	background-color: var(--bs-theme);
	color: var(--bs-theme-color);
	font-weight: 600;
	text-decoration: none;
	border-radius: 0 0 var(--bs-border-radius) 0;
}

.skip-link:focus {
	left: 0;
	color: var(--bs-theme-color);
}

/* -------------------------------------------------------------- hero band ---
   A white section carrying a faint red wash, so the top of the page has some
   brand in it without a dark band. The template's own .bg-component supplies the
   white; this only adds the tint and the hairline under it. */
.hero {
	background-color: var(--bs-component-bg);
	background-image: radial-gradient(60rem 32rem at 12% -20%, rgba(var(--bs-theme-rgb), .10), transparent 62%);
	border-bottom: 1px solid var(--bs-border-color);
}

/* ------------------------------------------------------------- UI drawing ---
   The illustrations on Home and the device pages are inline SVG, not screenshots:
   a real capture of the app shows whatever the tester's playlist held, which must
   never appear here. See README section 5 before replacing one.
   The drawing is dark because a television screen is dark - it sits inside a white
   template .card, which is the frame. */
.mockup-screen {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--bs-border-radius);
}

/* --------------------------------------------------------------- accents ---
   Accent and neutral values come from the reference palette the product owner
   supplied (2026-09-24). The page stays light and panel-matching; only these
   values were taken from it. Brand red is untouched and still owns every button.

   Premium is the ONE accented area, and its accent is the reference cyan
   #00B8FC (it replaced #0E79FB, which was close enough that two blues fought).

   TEXT ON THE CYAN IS DARK, NOT WHITE. White on #00B8FC measures 2.27:1, below
   the 4.5:1 minimum, and the owner's own inspector flagged exactly this pair as
   its one contrast issue. #021D2C from the same palette gives 7.40:1. */
/* Icons only (the feature ticks and the key on the Premium card), never text.
   #00B8FC on white is 2.27:1, under the 3:1 that WCAG 1.4.11 asks of a
   meaningful icon; this darker step from the same hue gives 3.42:1. Fills,
   borders and buttons keep the full #00B8FC because they carry dark text. */
.text-premium {
	color: #0093CA !important;
}

.border-premium {
	border-color: #00B8FC !important;
}

.bg-premium-subtle {
	background-color: rgba(0, 184, 252, .08) !important;
}

/* A solid premium fill, for the badge on the Premium card. .btn-premium below
   only sets --bs-btn-* variables, which a .badge does not read - using it there
   produced white text on nothing. */
.bg-premium {
	background-color: #00B8FC !important;
	color: #021D2C !important;
}

/* Success green, for the ticks on the free tier. The template's own --bs-success
   is re-pointed rather than a new class added, so any .text-success / .bg-success
   in the template picks it up unchanged. 5.61:1 on white. */
:root,
:root[data-bs-theme="light"],
body {
	--bs-success: #037909;
	--bs-success-rgb: 3, 121, 9;
}

/* Neutral text. The template builds muted text as an alpha of the body colour,
   which lands on a different grey over a white card than over a #EBEEF4 one.
   These are solid, so they read the same on every surface.

   NOTE ON WHICH GREYS. The reference palette is a DARK theme, so its light
   greys are sized for a #021D2C background. Ported onto a light page they stop
   working, and the page has two surfaces to satisfy, white cards and the
   #EBEEF4 band:

       #9598A2   white 2.88:1   band 2.48:1   unusable
       #707279   white 4.80:1   band 4.13:1   fails on the band
       #53555C   white 7.44:1   band 6.40:1   ok
       #303133   white 13.0:1   band 11.2:1   ok

   So the two darkest values carry the neutral text and the two light ones go
   unused. Everything here clears AA on both surfaces. */
.text-body.text-opacity-75 {
	color: #303133 !important;
}

.text-body.text-opacity-50 {
	color: #53555C !important;
}

/* Matches the shape and weight of the template's .btn-theme exactly - only the
   colour variables differ, so it stays a template button. Label is the dark
   navy for contrast, per the note above. */
.btn-premium {
	--bs-btn-color: #021D2C;
	--bs-btn-bg: #00B8FC;
	--bs-btn-border-color: #00B8FC;
	--bs-btn-hover-color: #021D2C;
	--bs-btn-hover-bg: #00A2DE;
	--bs-btn-hover-border-color: #0098D1;
	--bs-btn-focus-shadow-rgb: 0, 184, 252;
	--bs-btn-active-color: #021D2C;
	--bs-btn-active-bg: #0093CA;
	--bs-btn-active-border-color: #0089BD;
	--bs-btn-disabled-color: #021D2C;
	--bs-btn-disabled-bg: #00B8FC;
	--bs-btn-disabled-border-color: #00B8FC;
}

/* ---------------------------------------------------- legal placeholders ---
   Every unfilled value on a legal page is wrapped in <span class="ph">, so an
   unreviewed page is obvious on sight rather than something you have to hunt for
   in the source. check.ps1 counts them and that count is the deploy gate.
   Delete the span along with the placeholder text when you fill one in - do NOT
   just restyle it away. */
.ph {
	padding: .05em .4em;
	border-radius: var(--bs-border-radius-sm);
	background-color: var(--bs-theme);
	color: var(--bs-theme-color);
	font-weight: 600;
	font-size: .9em;
	white-space: nowrap;
}

/* ------------------------------------------------------------- long-form ---
   The keyword landing pages and the legal pages are mostly prose inside a card.
   A measure cap is the only thing the template does not supply, because nothing in
   an admin panel is read a paragraph at a time. */
/* Narrow the CARD, not the text inside it. A comfortable measure is about 75
   characters; a .container-xl card is far wider than that. Capping the
   paragraphs alone left a full-width card with a third of it blank, which reads
   as a bug rather than as a measure, so the card is what shrinks. At this width
   the body text lands near 75 characters on its own and needs no cap, which
   also leaves tables and the numbered step grids free to use the full card. */
.prose-card {
	max-width: 58rem;
	margin-left: auto;
	margin-right: auto;
}

.prose h2 {
	margin-top: 2.5rem;
}

.prose h3 {
	margin-top: 1.75rem;
}

.prose > :first-child {
	margin-top: 0;
}

/* Wide comparison tables on a phone. Opt in per table with .table-responsive on the
   wrapper; this only stops the columns collapsing to one word per line first. */
.prose .table th,
.prose .table td {
	vertical-align: top;
}

/* --------------------------------------------------------------- footer ---
   Light, to match the panel. The template's landing footer is bg-gray-800 with a
   dark scheme; that band is the one thing from landing.html deliberately not
   carried over, because the panels have no dark chrome anywhere. */
#footer h5 {
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
}


/* ==========================================================================
   PART 3 - typography
   Replaces the template's own type scale with the one the product owner
   supplied (2026-09-24), taken from a reference site's computed styles.
   ========================================================================== */

/* BROWN IS A COMMERCIAL TYPEFACE (Lineto) AND IS NOT BUNDLED.
   It leads the stack exactly as the reference does. A browser skips a family it
   does not have, so today every visitor gets a fallback:
     Android / Chrome OS -> Roboto
     macOS / iOS         -> Helvetica Neue
     Windows             -> Arial Nova, or Arial on older builds
     Linux               -> Nimbus Sans or Arial
   To actually ship Brown you need a Lineto web licence, the woff2 files in
   assets/fonts/, and an @font-face block here. Do NOT load it from a CDN: most
   users are in the EU and that hands a third party their IP addresses.
   Note this drops Segoe UI, so Windows moves from Segoe UI to Arial Nova. That
   is what the reference stack does; it is a real change, not an oversight. */
:root,
:root[data-bs-theme="light"],
:root[data-bs-theme="dark"],
body {
	--bs-body-font-family: Brown, Roboto, "Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
	--bs-body-font-size: 16px;
	--bs-body-line-height: 1.5;
}

/* Sizes are hard pixels, so the 112.5% desktop root scale in PART 1 no longer
   moves the text. That is deliberate: the root scale still grows the template's
   paddings, header and sidebar so the chrome keeps matching the panel, while
   the type follows the reference scale at every width. */
h1, .h1,
h2, .h2,
h3, .h3,
h4, .h4,
h5, .h5,
h6, .h6 {
	font-weight: 700;
	line-height: 1.15;
}

h1, .h1 { font-size: 31px; }
h2, .h2 { font-size: 28px; }
h3, .h3 { font-size: 20px; }
h4, .h4 { font-size: 18px; }
h5, .h5 { font-size: 16px; }
h6, .h6 { font-size: 14px; }

/* The page title on every page carries .display-6. The template pairs that with
   font-weight 300, which is far too light next to a 700 heading scale. */
.display-6 {
	font-size: 31px;
	font-weight: 700;
	line-height: 1.1;
}

@media (min-width: 992px) {
	h1, .h1 { font-size: 36px; }
	h2, .h2 { font-size: 36px; }
	.display-6 { font-size: 52px; }
}

/* Body copy inside a prose card. The template ships 0.875rem for dense admin
   tables; a marketing page is read a paragraph at a time and wants the 16px the
   reference uses. */
.prose p,
.prose li {
	font-size: 16px;
	line-height: 1.6;
}

/* ------------------------------------------------------------------ links ---
   Inline links in body copy: no underline at rest, underline on hover and on
   keyboard focus.

   The weight is not decoration. With the underline gone, a link at rest is set
   apart from the text around it by colour alone, and WCAG 1.4.1 only allows
   that when the link colour clears 3:1 against the surrounding text. Brand red
   #E10611 against body #212837 is 1.71:1, nowhere near it. The heavier weight
   is the second, non-colour cue that makes the rule satisfiable.

   Scoped to content links inside #main. Buttons, nav links, dropdown items,
   footer links, breadcrumbs and the card-wrapping anchors already carry
   .text-decoration-none and must not gain an underline on hover. */
#main p a,
#main li:not(.breadcrumb-item) a,
#main td a {
	font-weight: 600;
	text-decoration: none;
}

#main p a:hover,
#main p a:focus-visible,
#main li:not(.breadcrumb-item) a:hover,
#main li:not(.breadcrumb-item) a:focus-visible,
#main td a:hover,
#main td a:focus-visible {
	text-decoration: underline;
}

/* ------------------------------------------------------- one bold weight ---
   BOLD TEXT MUST BE 700, NOT 800.

   The template ships `b,strong{font-weight:800}` and `.fw-bold{font-weight:600}`,
   which is fine when a variable or multi-weight webfont is loaded. We have no
   webfont, so every visitor falls back to a system family that ships exactly two
   weights: Arial 400/700, Helvetica Neue 400/700, Roboto 400/700. Asking for 800
   matches nothing, so the browser SYNTHESIZES it by smearing the 700 face. The
   result is visibly heavier and slightly misshapen next to the body text, which
   reads as a different typeface rather than as bold. Asking for 600 rounds the
   other way and can come back lighter than the 700 headings beside it.

   Pinning both to 700 means bold is the real Bold face of the same family, and
   the same weight the headings use. Do not reintroduce 600, 800 or `bolder`
   here unless a real multi-weight font is being loaded. */
b,
strong {
	font-weight: 700;
}

.fw-bold {
	font-weight: 700 !important;
}
