. Those
+ classes are restyled here rather than in the templates, so the generated
+ pages keep building from their own sources and still land inside the portal
+ frame. */
+.band { display: block; }
+.wrap { width: 100%; margin: 0; padding: 0; }
+.wrap-narrow { max-width: 640px; }
+
+.doc h1, .band h1 {
+ font-size: 17px; color: #003399; margin: 0 0 6px;
+ padding-bottom: 3px; border-bottom: 1px solid var(--fn-rule);
+}
+.doc h2, .band h2 {
+ font-size: 13px; color: #003399; margin: 14px 0 4px;
+}
+.doc h3, .band h3 { font-size: 12px; color: var(--fn-chan); margin: 10px 0 3px; }
+.doc h4, .band h4 { font-size: 11px; color: var(--fn-ink-2); margin: 8px 0 3px; }
+
+.doc p, .band p { margin: 0 0 7px; font-size: 11px; line-height: 1.5; }
+.doc ul, .doc ol, .band ul, .band ol { margin: 0 0 8px 18px; }
+.doc li, .band li { margin: 0 0 3px; font-size: 11px; line-height: 1.5; }
+
+.doc table, .band table { border-collapse: collapse; margin: 0 0 10px; font-size: 11px; }
+.doc th, .doc td, .band th, .band td {
+ border: 1px solid var(--fn-rule); padding: 3px 6px; text-align: left; vertical-align: top;
+}
+.doc th, .band th { background: #E8EFF8; font-weight: bold; }
+
+/* A table in a generated page has no wrapper to scroll inside, and those
+ templates are built from docs so they cannot be given one. Making the table
+ a block gives it its own scroll container, and its rows still lay out as a
+ table inside. The comparison table already sits in .compare-scroll. */
+.doc table:not(.compare), .band table:not(.compare) {
+ display: block;
+ width: max-content;
+ max-width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.doc hr { border: 0; border-top: 1px solid var(--fn-rule); margin: 12px 0; }
+
+.doc blockquote {
+ margin: 0 0 8px; padding: 5px 8px;
+ background: #F5F8FC; border-left: 3px solid var(--fn-chan);
+}
+
+.eyebrow {
+ display: block; font-size: 10px; font-weight: bold;
+ letter-spacing: .06em; text-transform: uppercase; color: var(--fn-chan);
+ margin-bottom: 3px;
+}
+.lede { margin: 0 0 9px; font-size: 12px; line-height: 1.5; color: var(--fn-ink-2); }
+.lede-wide, .band-lede { max-width: none; }
+.band-lede-spaced { margin-top: 9px; }
+.meta, .fineprint { font-size: 10px; color: var(--fn-ink-3); margin: 0 0 8px; }
+.hl { color: var(--fn-chan); }
+
+.callout {
+ margin: 0 0 10px; padding: 6px 8px;
+ background: #FFFBE6; border: 1px solid #E0C878;
+}
+.callout p { margin: 0; }
+
+/* Code. Monospace on a tinted panel, and long unbroken strings wrap: a
+ sixty-four character hash has no spaces and would push the column sideways. */
+code, kbd, samp {
+ font-family: "Courier New", Courier, monospace; font-size: 11px;
+ background: #F1F4F9; border: 1px solid #DCE4F0; padding: 0 3px;
+}
+pre {
+ margin: 0 0 10px; padding: 6px 8px;
+ background: #F1F4F9; border: 1px solid var(--fn-rule);
+ overflow-x: auto; font-size: 11px; line-height: 1.45;
+}
+pre code { background: none; border: 0; padding: 0; }
+.code, .json, .bash, .js { display: block; }
+.code-light { background: #FAFCFF; }
+
+.btn, a.btn {
+ display: inline-block;
+ padding: 3px 12px; margin: 0 3px 3px 0;
+ background: linear-gradient(180deg, #FCFBF6 0%, #E7E3D3 52%, #D4CEB9 100%);
+ border: 1px solid #87826E; border-radius: 2px;
+ font-size: 11px; font-weight: bold; color: #000000;
+ font-family: Tahoma, Arial, sans-serif; cursor: pointer; text-decoration: none;
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.85);
+}
+a.btn:visited { color: #000000; }
+.btn:hover, a.btn:hover {
+ background: linear-gradient(180deg, #FFFFFF 0%, #F1EEE3 52%, #DED8C5 100%);
+ color: #000000; text-decoration: none;
+}
+
+/* The one button per page that is the thing to do. Gold on navy, which is the
+ portal's own accent pair. */
+.btn-primary, a.btn-primary {
+ background: linear-gradient(180deg, #596EBB 0%, #1835A0 50%, #13297D 100%);
+ border-color: #122678; color: #FFFFFF;
+}
+.btn-primary:visited, a.btn-primary:visited { color: #FFFFFF; }
+.btn-primary:hover, a.btn-primary:hover {
+ background: linear-gradient(180deg, #6B80CC 0%, #2445B5 50%, #18328F 100%);
+ color: var(--fn-gold);
+}
+
+.btn-nav, a.btn-nav { background: var(--fn-gold); border-color: #D1A700; color: #004E82; }
+.btn-nav:visited, a.btn-nav:visited { color: #004E82; }
+
+.cta-row { margin: 8px 0 4px; }
+
+/* Feature grids become module rows. Cards keep their class names so the
+ product pages need no rewrite beyond their own layout. */
+.cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 0 0 10px; }
+.cards-3 { grid-template-columns: repeat(3, 1fr); }
+.cards-4 { grid-template-columns: repeat(4, 1fr); }
+.card {
+ padding: 6px 8px; background: #F7FAFD;
+ border: 1px solid var(--fn-rule); box-shadow: 0 1px 2px rgba(0,22,52,0.12);
+}
+.card h3 { margin: 0 0 3px; font-size: 11px; color: #003399; }
+.card p { margin: 0 0 4px; font-size: 11px; }
+.card-icon { display: none; }
+.card-link { font-size: 10px; font-weight: bold; }
+
+.honest { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 0 0 10px; }
+.honest-card {
+ padding: 6px 8px; background: #FFFFFF;
+ border: 1px solid var(--fn-rule); border-top: 3px solid var(--fn-chan);
+}
+.honest-card h3 { margin: 0 0 3px; font-size: 11px; }
+.honest-card p { margin: 0; font-size: 11px; }
+
+.stack-note {
+ margin: 10px 0 0; padding: 6px 8px;
+ background: #F5F8FC; border: 1px solid var(--fn-rule); font-size: 11px;
+}
+.proof { display: flex; flex-wrap: wrap; gap: 3px 14px; font-size: 11px; margin: 4px 0 0; }
+.proof-lead { margin: 0; font-size: 11px; }
+.chip { display: inline-block; margin-right: 10px; font-size: 11px; }
+.chip-ic { display: none; }
+.hero-chips { margin: 6px 0 0; }
+
+/* Donation form. Stripe styles its own fields, so this covers the frame,
+ the amount choices and the errors only. */
+.donate-form {
+ margin: 0 0 12px; padding: 8px 10px;
+ background: #F7FAFD; border: 1px solid var(--fn-rule);
+}
+.donate-form fieldset { border: 0; padding: 0; margin: 0 0 10px; }
+.donate-form legend {
+ padding: 0; margin-bottom: 5px;
+ font-size: 10px; font-weight: bold; letter-spacing: .06em;
+ text-transform: uppercase; color: var(--fn-ink-3);
+}
+.donate-freq, .donate-amounts { display: flex; flex-wrap: wrap; gap: 4px; }
+
+.donate-form label {
+ display: inline-flex; align-items: center; gap: 5px;
+ padding: 3px 10px;
+ background: linear-gradient(180deg, #FCFBF6 0%, #E7E3D3 52%, #D4CEB9 100%);
+ border: 1px solid #87826E; border-radius: 2px;
+ font-size: 11px; font-weight: bold; cursor: pointer;
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.85);
+}
+.donate-form label:hover { background: linear-gradient(180deg, #FFFFFF 0%, #F1EEE3 52%, #DED8C5 100%); }
+/* The radio stays focusable and in the accessibility tree, so it is moved
+ rather than hidden. */
+.donate-form input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; }
+.donate-form label:has(input[type="radio"]:checked) {
+ background: linear-gradient(180deg, #596EBB 0%, #1835A0 50%, #13297D 100%);
+ border-color: #122678; color: #FFFFFF;
+}
+.donate-form label:has(input[type="radio"]:focus-visible) {
+ outline: 2px solid var(--fn-gold); outline-offset: 1px;
+}
+
+.donate-custom input[type="number"],
+.donate-email input[type="email"] {
+ padding: 2px 5px; font-family: Tahoma, Arial, sans-serif; font-size: 11px;
+ border: 1px solid #6E8AA6; background: #FFFFFF;
+ box-shadow: inset 1px 1px 2px rgba(0,0,0,0.18);
+}
+.donate-custom input[type="number"] { width: 70px; }
+.donate-email { margin: 8px 0 4px; }
+.donate-email label {
+ display: block; padding: 0; border: 0; background: none;
+ box-shadow: none; cursor: default;
+ font-size: 10px; font-weight: bold; letter-spacing: .06em;
+ text-transform: uppercase; color: var(--fn-ink-3); margin-bottom: 4px;
+}
+.donate-email label:hover { background: none; }
+.donate-email input[type="email"] { width: 100%; max-width: 280px; }
+
+.donate-payment { margin: 4px 0 10px; padding-top: 10px; border-top: 1px solid var(--fn-rule); }
+.donate-error {
+ margin: 0 0 8px; padding: 5px 8px;
+ background: #FDECEC; border: 1px solid #D69A9A; color: #9B1C1C; font-size: 11px;
+}
+.donate-thanks {
+ margin: 0 0 12px; padding: 6px 8px;
+ background: #EAF3ED; border: 1px solid #2B804C;
+}
+.donate-thanks p { margin: 3px 0 0; font-size: 11px; }
+.donate-pending {
+ padding: 6px 8px; background: #F5F8FC;
+ border: 1px dashed var(--fn-rule); color: var(--fn-ink-3);
+}
+
+/* Comparison table. Wide, so it scrolls inside its own box rather than
+ widening the column. */
+.compare-scroll { overflow-x: auto; margin: 0 0 12px; -webkit-overflow-scrolling: touch; }
+.compare { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 11px; }
+.compare th, .compare td {
+ border: 1px solid var(--fn-rule); padding: 4px 6px;
+ text-align: left; vertical-align: top;
+}
+.compare thead th { background: #E8EFF8; font-weight: bold; white-space: nowrap; }
+.compare tbody th { background: #F5F8FC; font-weight: bold; width: 24%; }
+.compare td { width: 19%; }
+/* Our own column is marked, since the comparison is written by one of the
+ products in it. */
+.compare .mine { background: var(--fn-chan-tint); }
+.compare thead th.mine { background: var(--fn-chan); color: #FFFFFF; }
+
+/* Install page panels. */
+.install-steps, .fdroid-block, .qr-hop, .verify-code {
+ margin: 10px 0 0; padding: 6px 8px;
+ background: #F7FAFD; border: 1px solid var(--fn-rule);
+}
+.install-steps h3, .fdroid-block h3 { margin: 0 0 4px; font-size: 12px; color: #003399; }
+.install-lede { margin: 0 0 6px; font-size: 11px; }
+.install-steps ol { margin: 0 0 0 18px; }
+.install-steps ol li, .install-hashes li { margin: 0 0 5px; font-size: 11px; line-height: 1.5; }
+.install-verify { margin: 8px 0 4px; font-size: 11px; }
+.install-hashes { margin: 0 0 0 18px; }
+.install-cmd { font-size: 10px; color: var(--fn-ink-3); }
+.install-foot, .fdroid-note {
+ margin: 8px 0 0; padding-top: 6px; border-top: 1px solid var(--fn-rule); font-size: 10px;
+}
+.fdroid-block p { margin: 0 0 6px; font-size: 11px; }
+.fdroid-steps { font-weight: bold; }
+.fdroid-fp { display: block; margin-top: 3px; font-size: 10px; }
+/* Hashes and fingerprints have no spaces to break at. */
+.install-hashes code, .fdroid-manual code, .fdroid-fp code, .verify-line code, .verify-code {
+ word-break: break-all;
+}
+.verify-code { display: block; white-space: pre-wrap; font-family: "Courier New", Courier, monospace; }
+.verify-line { font-size: 11px; line-height: 1.6; }
+.get-more { margin: 8px 0 0; font-size: 11px; }
+
+/* The QR is for moving from a desktop to the phone the app ends up on, so it
+ is hidden at phone widths where it would point at the page already open. */
+.qr-hop { display: flex; align-items: center; gap: 10px; text-align: left; }
+.qr-hop img { flex: none; width: 110px; height: 110px; display: block; }
+.qr-hop p { margin: 0; font-size: 11px; }
+
+/* Releases. The self-hosting note in each entry is written for an operator,
+ not for somebody holding a phone, so it is set apart. */
+.release { margin: 0 0 16px; padding-bottom: 12px; border-bottom: 1px solid #DCE4F4; }
+.release h2 { margin-bottom: 2px; }
+.release h2 small { font-weight: normal; color: var(--fn-ink-3); }
+.release-platforms { margin: 2px 0 5px; }
+.release-platforms .tag {
+ display: inline-block; font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
+ padding: 0 5px; margin-right: 3px;
+ background: #E8EFF8; border: 1px solid var(--fn-rule); color: var(--fn-ink-2);
+}
+.release .selfhost {
+ margin-top: 8px; padding: 5px 8px;
+ background: #F5F8FC; border-left: 3px solid var(--fn-chan);
+}
+.release .selfhost h3 { margin: 0 0 3px; font-size: 11px; }
+.pager { display: flex; gap: 10px; align-items: center; margin: 12px 0 0; font-size: 11px; }
+.pager-off { color: #999999; }
+.pager-at { color: var(--fn-ink-3); }
+
+/* Footer, the portal's terms bar. */
+#site-footer {
+ background: var(--fn-navy); padding: 8px 12px 12px 12px;
+ text-align: center; color: #FFFFFF;
+}
+#footer-links { margin-bottom: 6px; padding-bottom: 6px; border-bottom: 1px solid #6695B4; }
+#footer-links a, #footer-links a:visited {
+ color: #FFFFFF; text-decoration: none; font-size: 10px; margin: 0 6px;
+ display: inline-block; line-height: 1.8;
+}
+#footer-links a:hover { color: var(--fn-gold); text-decoration: underline; }
+/* The separate-app statement, in the same cream notice panel flamenet.io uses
+ for its counterpart (#footer-messenger there). Somebody who thinks one
+ account covers both sites has to read this, so it is a panel on the navy
+ rather than another line of fine print. */
+#footer-separate {
+ max-width: 780px; margin: 0 auto 8px; padding: 8px 12px;
+ font-size: 11px; line-height: 1.6; text-align: center;
+ color: #333333;
+ background: #FFF9E6;
+ border: 1px solid #E0C97F;
+}
+
+#footer-separate strong { color: #000000; }
+
+#footer-separate a,
+#footer-separate a:visited { color: #0000CC; text-decoration: underline; }
+
+#footer-separate a:hover { color: #CC0000; }
+
+#footer-copyright { font-size: 9px; color: #B4D2EE; margin-top: 2px; line-height: 1.5; }
+#footer-copyright a, #footer-copyright a:visited { color: var(--fn-gold); }
+#footer-copyright strong { color: #FFFFFF; }
+#footer-copyright .heart { color: #FF8FB0; }
+
+/* Stats strip above the footer, the portal's site weather bar. Numbers here
+ are the ones a relay can state without counting people. */
+#site-stats-bar {
+ background: #003399; color: #FFFFFF;
+ font-family: Arial, Helvetica, sans-serif; font-size: 11px;
+ padding: 5px 12px; border-top: 1px solid var(--fn-gold); text-align: center;
+}
+#site-stats-bar strong { color: var(--fn-gold); }
+#site-stats-bar a, #site-stats-bar a:visited { color: #FFFFFF; text-decoration: underline; }
+
+/* Stacked layout.
+
+ The three columns are table-cells, and table cells never wrap. At 375px the
+ fixed rails leave the centre column about 100px wide and the row still
+ demands more than the viewport, so the right rail becomes unreachable rather
+ than narrow. Stacking is the only thing a table layout can do at this width.
+ The look is kept: same gradients, same module chrome, the columns become
+ rows.
+
+ An overflow check will call the page clean either way, because the overflow
+ is clipped rather than scrolled. Measure scrollWidth against clientWidth. */
+@media (max-width: 860px) {
+ #content-area { display: block; width: 100%; }
+
+ #directory-column, #main-column, #sidebar-column {
+ display: block; width: auto;
+ box-shadow: none;
+ }
+
+ /* The rail stays first, where navigation is looked for. Its links flow and
+ wrap instead of stacking into a vertical wall. */
+ #directory-column ul, #directory-column .lcol-list {
+ display: flex; flex-wrap: wrap; gap: 2px 6px; margin: 0 0 6px 0;
+ }
+ /* 11px text with 1px of padding is a 15px tap target, which is fine for a
+ mouse and not for a thumb. */
+ #directory-column li a { display: inline-block; font-size: 13px; padding: 6px 8px; }
+
+ #main-column, #sidebar-column { border-top: 1px solid #9BB6D4; }
+
+ /* Title left, search right, with a fixed 150px box that refuses to give way.
+ They stay on one line whenever they fit. */
+ #channel-masthead { flex-wrap: wrap; gap: 6px 10px; }
+ .channel-search { flex-wrap: wrap; }
+ .channel-search input[type="search"] { width: auto; flex: 1 1 130px; min-width: 0; }
+
+ summary.lcol-hd {
+ cursor: pointer; position: relative;
+ padding: 8px 24px 8px 2px; font-size: 13px;
+ }
+ summary.lcol-hd::after {
+ content: '+'; position: absolute; right: 6px; top: 50%;
+ margin-top: -0.6em; font-size: 15px; line-height: 1;
+ }
+ .lcol-sec[open] > summary.lcol-hd::after { content: '\2212'; }
+ .lcol-sec[open] > .lcol-list, .lcol-sec[open] > ul { margin-top: 4px; }
+
+ .cards, .cards-3, .cards-4, .honest { grid-template-columns: 1fr; }
+ .qr-hop { display: none; }
+}
+
+/* Bands as module boxes.
+
+ Every page body is a stack of
or
+ , each holding a .wrap. Styling that stack as the
+ portal's module boxes is what makes all of the pages portal pages without
+ editing a template, which matters for the nine pages generated from docs.
+
+ The heading becomes the coloured header bar and the eyebrow becomes the pale
+ tag strip above it, which is the same pair the theme's own page shell uses.
+ Both are pulled full bleed with negative margins so the .wrap keeps its
+ padding for everything else. */
+.band {
+ margin: 0 0 13px;
+ background: #FFFFFF;
+ border: 1px solid var(--fn-rule);
+ box-shadow: 0 1px 3px rgba(0,22,52,0.22);
+}
+.band > .wrap { padding: 0 8px 7px; }
+
+.band > .wrap > .eyebrow,
+.band > .wrap > .band-head > .eyebrow {
+ display: block; margin: 0 -8px 0 -8px; padding: 3px 8px;
+ background: #EEF2FF; color: #003399;
+ font-size: 10px; font-weight: bold; letter-spacing: .06em; text-transform: uppercase;
+ border-bottom: 1px solid var(--fn-rule);
+}
+
+.band > .wrap > h1,
+.band > .wrap > h2,
+.band > .wrap > .band-head > h2 {
+ margin: 0 -8px 7px -8px; padding: 3px 8px;
+ background-color: var(--fn-chan);
+ background-image: linear-gradient(180deg, rgba(255,255,255,0.28) 0%, rgba(255,255,255,0) 50%, rgba(0,0,0,0.22) 100%);
+ color: #FFFFFF;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px; font-weight: bold;
+ border: 0;
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.32);
+ text-shadow: 0 1px 1px rgba(0,0,0,0.32);
+}
+.band > .wrap > h1 .hl,
+.band > .wrap > h2 .hl,
+.band > .wrap > .band-head > h2 .hl { color: var(--fn-gold); }
+
+/* The portal gives consecutive modules different header colours. Element types
+ in the stack are mixed, so the cycle is uneven, which is what these pages
+ looked like anyway. */
+.band:nth-of-type(7n+2) > .wrap > h2, .band:nth-of-type(7n+2) > .wrap > .band-head > h2 { background-color: #CC6600; }
+.band:nth-of-type(7n+3) > .wrap > h2, .band:nth-of-type(7n+3) > .wrap > .band-head > h2 { background-color: #2B804C; }
+.band:nth-of-type(7n+4) > .wrap > h2, .band:nth-of-type(7n+4) > .wrap > .band-head > h2 { background-color: #1835A0; }
+.band:nth-of-type(7n+5) > .wrap > h2, .band:nth-of-type(7n+5) > .wrap > .band-head > h2 { background-color: #635190; }
+.band:nth-of-type(7n+6) > .wrap > h2, .band:nth-of-type(7n+6) > .wrap > .band-head > h2 { background-color: #446CC0; }
+.band:nth-of-type(7n+7) > .wrap > h2, .band:nth-of-type(7n+7) > .wrap > .band-head > h2 { background-color: #9E4040; }
+
+.band-alt { background: #FAFCFF; }
+.band-center, .band-head { text-align: left; }
+.fineprint-flush { margin-bottom: 0; }
+.doc-generated { }
+
+/* The landing splash. A channel-coloured promo box with the copy on the left
+ and the app on the right, which is where a product section of a portal put
+ the thing it wanted you to download. */
+.hero {
+ margin: 0 0 13px;
+ background-color: var(--fn-chan);
+ background-image: linear-gradient(180deg, #A94062 0%, var(--fn-chan) 52%, #7A2A45 100%);
+ border: 1px solid var(--fn-chan-dark);
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.25), 0 1px 3px rgba(0,22,52,0.3);
+}
+.hero-inner { display: flex; align-items: center; gap: 14px; padding: 12px 12px 14px; }
+.hero-copy { flex: 1 1 auto; min-width: 0; }
+.hero .eyebrow {
+ display: block; background: none; border: 0; padding: 0; margin: 0 0 3px;
+ color: rgba(255,255,255,0.85);
+}
+.hero h1 {
+ margin: 0 0 6px; padding: 0; border: 0; background: none;
+ font-size: 22px; line-height: 1.15; color: #FFFFFF;
+ text-shadow: 0 1px 2px rgba(0,0,0,0.4);
+}
+.hero h1 .hl { color: var(--fn-gold); }
+.hero .lede { color: #FFFFFF; font-size: 12px; max-width: 42em; }
+.hero .chip { color: #FFFFFF; font-weight: bold; }
+.hero .chip::before { content: '\2713\00a0'; color: var(--fn-gold); }
+.hero-art { flex: none; }
+.phone { display: block; }
+.phone-screen {
+ display: block; width: 132px; height: auto;
+ border: 2px solid rgba(0,0,0,0.35); background: #FFFFFF;
+ box-shadow: 0 2px 6px rgba(0,0,0,0.35);
+}
+
+/* The facts strip under the splash. */
+.proof-band {
+ margin: 0 0 13px; padding: 5px 8px;
+ background: #E8EFF8; border: 1px solid var(--fn-rule);
+}
+.proof-band .wrap { padding: 0; }
+
+/* Numbered steps. The number is a small square counter, not a circle. */
+.steps { list-style: none; margin: 0; padding: 0; }
+.step { position: relative; padding: 0 0 8px 22px; }
+.step-n {
+ position: absolute; left: 0; top: 1px;
+ width: 16px; height: 16px; line-height: 16px; text-align: center;
+ background: var(--fn-chan); color: #FFFFFF;
+ font-weight: bold; font-size: 10px;
+ font-family: Arial, Helvetica, sans-serif;
+}
+.step h3 { margin: 0 0 2px; font-size: 11px; color: #003399; }
+.step p { margin: 0; }
+
+/* Download choices. A row of beveled tiles, one per platform. */
+.platforms { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin: 0 0 8px; }
+.platform, a.platform, a.platform:visited {
+ display: block; padding: 5px 8px; text-decoration: none; color: #000000;
+ background: linear-gradient(180deg, #FCFBF6 0%, #EFECE0 52%, #DED8C5 100%);
+ border: 1px solid #87826E;
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.85);
+}
+a.platform:hover { background: linear-gradient(180deg, #FFFFFF 0%, #F6F3E9 52%, #E7E1CF 100%); color: #000000; }
+.platform-name { display: block; font-weight: bold; font-size: 11px; color: #003399; }
+.platform-state { display: block; font-size: 10px; color: var(--fn-ink-3); }
+
+/* Two columns inside a module, copy beside a command block. */
+.split { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; }
+
+/* Comparison verdicts. A word, then its note on the next line. */
+.yes { color: #1E6B3A; font-weight: bold; }
+.no { color: #9E2020; font-weight: bold; }
+
+/* Community page cards. */
+.commun { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 0 0 10px; }
+.commun-card {
+ padding: 6px 8px; background: #F7FAFD;
+ border: 1px solid var(--fn-rule); border-top: 3px solid var(--fn-chan);
+}
+.commun-card h3 { margin: 0 0 3px; font-size: 11px; color: #003399; }
+.commun-ic { display: none; }
+.commun-inf { font-size: 10px; color: var(--fn-ink-3); }
+
+/* Grouped headings inside a document, and the spec's numbered parts. */
+.group-head { margin: 12px 0 4px; font-size: 12px; color: #003399; font-weight: bold; }
+.part { margin: 0 0 10px; }
+
+/* Frequently asked questions. Closed by default, opened one at a time. */
+.faq details {
+ margin: 0 0 4px; background: #F7FAFD; border: 1px solid var(--fn-rule);
+}
+.faq summary {
+ padding: 3px 6px; cursor: pointer;
+ font-weight: bold; font-size: 11px; color: #003399;
+}
+.faq details p { margin: 0; padding: 0 6px 6px; }
+
+.btn-ghost, a.btn-ghost { background: linear-gradient(180deg, #FCFBF6 0%, #E7E3D3 52%, #D4CEB9 100%); }
+.btn-outline, a.btn-outline { background: #FFFFFF; }
+
+@media (max-width: 860px) {
+ .hero-inner { flex-wrap: wrap; }
+ .hero-art { order: -1; }
+ .platforms { grid-template-columns: repeat(2, 1fr); }
+ .split, .commun { grid-template-columns: 1fr; }
+}
diff --git a/Resources/Views/es/landing.leaf b/Resources/Views/es/landing.leaf
index 3407eed..56aab01 100644
--- a/Resources/Views/es/landing.leaf
+++ b/Resources/Views/es/landing.leaf
@@ -10,7 +10,6 @@
Sin número de teléfono
@@ -86,120 +85,6 @@
-
-
-
Nuevo en la app
-
Cinco cosas nuevas en el mensajero .
-
- Cada una funciona como funciona el resto de la app.
-
-
- Una encuesta que nadie puede atribuir. Pregúntale algo a
- un grupo y el voto de nadie se le envía a nadie, tampoco a ti que
- preguntas. Cada voto se parte en trozos aleatorios, uno por miembro, y
- cada cual publica solo la suma de los trozos que le tocaron. Sumando esas
- sumas salen los recuentos. Todos los demás tendrían que ponerse de acuerdo
- para saber lo que votó una persona.
-
-
- Pasa una llamada a otro dispositivo. Estás en una llamada
- en el teléfono, la coges en la tableta y sigues hablando. La otra persona
- oye un hueco corto, se queda donde está, y le queda una llamada en su
- registro y no dos.
-
-
- Una reacción que solo ve esa persona. En un grupo,
- reacciona a quien lo escribió en vez de a toda la sala. A nadie más se le
- envía.
-
-
- Reacciona durante una llamada. Di que sí sin interrumpir.
- Se ve un momento y no se guarda nada.
-
-
- Fuera de registro. Los dos teléfonos dejan de escribir la
- conversación. Cierra la app y ya no está. Lo acuerdan los dos teléfonos,
- así que no puede estar activo para uno y no para el otro.
-
-
- En Android desde la versión 0.18. En iPhone, en la próxima compilación de
- TestFlight.
-
-
-
-
-
-
-
-
Conviene saberlo
-
Unas cuantas cosas que conviene saber .
-
- Toda aplicación de mensajería tiene límites. Estos son los nuestros, dichos con claridad, para que nada de cómo funciona esto te sorprenda más adelante.
-
-
-
-
-
- Que los servidores hablen entre ellos significa que más servidores ven algo
-
- Cuando dos servidores se intercambian un mensaje, cada uno se entera de que el otro tenía tráfico para él. Nadie lee el mensaje, pero el hecho de que exista queda repartido entre más operadores de los que habría con un solo servidor. Ese es el precio de poder marcharte, y por eso un operador tiene que activarlo a propósito en lugar de encontrárselo ya puesto.
-
-
-
- El cifrado cubre el mensaje, no el hecho de que lo enviaste
-
- Nuestro servidor tiene que saber a quién entregar un mensaje, así que puede ver que le escribiste a alguien y más o menos cuándo. No puede leer ni una palabra de lo que dijiste. Eso vale para cualquier aplicación de mensajería que entregue a gente que está desconectada.
-
- Mira exactamente qué se guarda
-
-
- Todavía nos queda pendiente una auditoría externa
-
- El código es abierto y está muy probado, y el diseño está publicado para que cualquiera pueda revisarlo. Una revisión pagada a una empresa de seguridad es otro tipo de garantía, y es una que nos gustaría poder financiar.
-
- Qué cubriría una auditoría
-
-
-
-
-
-
-
-
Cómo funciona
-
Cómo tus mensajes siguen siendo privados .
-
- No necesitas nada de esto para usar la aplicación. Pero si alguna vez te has preguntado qué quiere decir de verdad "cifrado de extremo a extremo", se reduce a tres ideas.
-
-
-
- 1
- Tu teléfono fabrica una cerradura y una llave
-
- Reparte copias de la cerradura a quien quiera escribirte. La llave que las abre se queda en tu teléfono, y no se comparte ni con nosotros ni con nadie.
-
-
-
- 2
- Tu amigo cierra el mensaje antes de enviarlo
-
- Para cuando llega a nuestro servidor ya está cerrado, y nosotros no tenemos la llave. Ninguno de los dos tiene que estar conectado a la vez para que esto funcione.
-
-
-
- 3
- Cada mensaje lleva una cerradura nueva
-
- Las cerraduras van cambiando conforme avanza la conversación, así que aunque alguna llegara a abrirse, no serviría de nada con los mensajes anteriores.
-
-
-
-
- Las tres ideas tienen nombres técnicos propios, y si quieres la versión completa con los detalles, está todo en
- la especificación .
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
#(chrome.railProduct)
+
+
+
+ #(chrome.footDevelopers)
+
+
+
+
+ #(chrome.footProject)
+
+
+
+
+ #(chrome.footLegal)
+
+
+
+
#(chrome.railNote)
+
+
+
+
+#import("content")
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#(chrome.statsLine)
+
+